最近在为公司的几个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;
}