最近在為公司的幾個H5項目做app打包,然後就踩到這個坑了。
項目中有 h5調用相冊選擇圖檔,然後上傳這個功能,測試說上傳不了圖檔。然後搜了不少資料,折騰了一下午,終于搞好了,特此記錄下。
原生WebView 的選擇圖檔功能需要我們自己實作,代碼如下:
wv_main.setWebChromeClient(new WebChromeClient() {
// Andorid 4.1----4.4
public void openFileChooser(ValueCallback<uri> uploadFile, String acceptType, String capture) {
mFilePathCallback = uploadFile;
handle(uploadFile);
}
// for 5.0+
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<uri[]> filePathCallback, FileChooserParams fileChooserParams) {
if (mFilePathCallbackArray != null) {
mFilePathCallbackArray.onReceiveValue(null);
}
mFilePathCallbackArray = filePathCallback;
handleup(filePathCallback);
return true;
}
});
}
private void handle(ValueCallback<uri> uploadFile) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, PICK_REQUEST);
}
private void handleup(ValueCallback<uri[]> uploadFile) {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, PICK_REQUEST);
}
然後在Activity的onActivityResult 方法裡處理回調,代碼如下:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_REQUEST) {
if (null != data) {
Uri uri = data.getData();
handleCallback(uri);
} else {
// 取消了照片選取的時候調用
handleCallback(null);
}
} else {
// 取消了照片選取的時候調用
handleCallback(null);
}
}
/**
* 處理WebView的回調
*
* @param uri
*/
private void handleCallback(Uri uri) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mFilePathCallbackArray != null) {
if (uri != null) {
mFilePathCallbackArray.onReceiveValue(new Uri[]{uri});
} else {
mFilePathCallbackArray.onReceiveValue(null);
}
mFilePathCallbackArray = null;
}
} else {
if (mFilePathCallback != null) {
if (uri != null) {
String url = getFilePathFromContentUri(uri, getContentResolver());
Uri u = Uri.fromFile(new File(url));
mFilePathCallback.onReceiveValue(u);
} else {
mFilePathCallback.onReceiveValue(null);
}
mFilePathCallback = null;
}
}
}
坑1:記得一定要釋放,不然點取消之後,就再調不起來了(一下午主要就填這個坑了)
4.1-4.4
mFilePathCallback.onReceiveValue(null);
5.0
mFilePathCallbackArray.onReceiveValue(null);
坑2:4.4以下,傳回的Uri 是content: 開頭的,h5端識别不了,需要轉成絕對路徑
public static String getFilePathFromContentUri(Uri selectedVideoUri,
ContentResolver contentResolver) {
String filePath;
String[] filePathColumn = {MediaStore.MediaColumns.DATA};
Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
// 也可用下面的方法拿到cursor
// Cursor cursor = this.context.managedQuery(selectedVideoUri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
filePath = cursor.getString(columnIndex);
cursor.close();
return filePath;
}