本文参考:Android——UI篇:WebView里调用相机/文件选取照片并上传 - 简书
第一步:重写WebChromeClient中的openFileChooser/onShowFileChooser方法
第二步:在openFileChooser/onShowFileChooser中处理逻辑
public class WebActivity extends AppCompatActivity {
private ValueCallback mUploadCallbackAboveL;
private ValueCallback mUploadCallbackBelow;
private Uri imageUri;
private final int REQUEST_CODE_IMG = 10011;
private final int REQUEST_CODE_VIDEO = 10022;
private final String TAG = "WebActivity";
//省略无关代码
.....
@SuppressLint("SetJavaScriptEnabled")
@Override
protected void initView(Bundle savedInstanceState) {
WebSettings mSettings = mWebView.getSettings();
//省略无关代码
.....
//重写WebChromeClient 中的openFileChooser/onShowFileChooser方法
WebChromeClient chromeClient = new WebChromeClient() {
@Override
public void onPermissionRequest(PermissionRequest request) {
request.grant(request.getResources());
request.getOrigin();
}
@Override
public void onReceivedTitle(WebView view, String title) {
if (mTvTitle != null && !TextUtils.isEmpty(title)) {
mTvTitle.setText(title);
}
}
/**
* 16(Android 4.1.2) <= API <= 20(Android 4.4W.2)回调此方法
*/
public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) {
// 这里我们就不区分input的参数了,直接用拍照
mUploadCallbackBelow = uploadMsg;
openCamera("");
}
/**
* API >= 21(Android 5.0.1)回调此方法
*/
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback valueCallback, FileChooserParams fileChooserParams) {
// (1)该方法回调时说明版本API >= 21,此时将结果赋值给 mUploadCallbackAboveL,使之 != null
mUploadCallbackAboveL = valueCallback;
String[] acceptTypes = fileChooserParams.getAcceptTypes();
if (acceptTypes.length > 0) {
openCamera(acceptTypes[0]);
LoggerUtils.e(TAG, "类型:" + acceptTypes[0]);
}
return true;
}
};
mWebView.setWebChromeClient(chromeClient);
}
//省略无关代码
.....
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_VIDEO) {
if (null != mUploadCallbackBelow) {
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
mUploadCallbackBelow.onReceiveValue(result);
mUploadCallbackBelow = null;
} else if (null != mUploadCallbackAboveL) {
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
if (result != null) {
mUploadCallbackAboveL.onReceiveValue(new Uri[]{result});
} else {
mUploadCallbackAboveL.onReceiveValue(null);
}
mUploadCallbackAboveL = null;
}
} else if (requestCode == REQUEST_CODE_IMG) {
// 经过上边(1)、(2)两个赋值操作,此处即可根据其值是否为空来决定采用哪种处理方法
if (mUploadCallbackBelow != null) {
chooseBelow(resultCode, data);
} else if (mUploadCallbackAboveL != null) {
chooseAbove(resultCode, data);
} else {
ToastUtils.showShort("发生错误");
}
}
}
/**
* 调用相机/相册选择器弹窗
*/
private void openCamera(String accept) {
if (accept.contains("video")) {
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);//设置视频录制的质量,0为低质量,1为高质量。
//intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 6);//限制时长 单位秒
//intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 1024L * 1024 * 10);//指定视频最大允许的尺寸,单位为byte
//开启摄像机
startActivityForResult(intent, REQUEST_CODE_VIDEO);
} else {
// 指定拍照存储位置的方式调起相机
String filePath = Environment.getExternalStorageDirectory() + File.separator
+ Environment.DIRECTORY_PICTURES + File.separator;
String fileName = "IMG_" + DateFormat.format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".jpg";
imageUri = Uri.fromFile(new File(filePath + fileName));
// Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
// startActivityForResult(intent, REQUEST_CODE_IMG);
// 选择图片(不包括相机拍照),则不用成功后发刷新图库的广播
// Intent i = new Intent(Intent.ACTION_GET_CONTENT);
// i.addCategory(Intent.CATEGORY_OPENABLE);
// i.setType("image/*");
// startActivityForResult(Intent.createChooser(i, "Image Chooser"), REQUEST_CODE_IMG);
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
Intent photo = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent chooserIntent = Intent.createChooser(photo, "Image Chooser");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
startActivityForResult(chooserIntent, REQUEST_CODE_IMG);
}
}
/**
* Android API < 21(Android 5.0)版本的回调处理
*
* @param resultCode 选取文件或拍照的返回码
* @param data 选取文件或拍照的返回结果
*/
private void chooseBelow(int resultCode, Intent data) {
LoggerUtils.d(TAG, "返回调用方法--chooseBelow");
if (RESULT_OK == resultCode) {
updatePhotos();
if (data != null) {
// 这里是针对文件路径处理
Uri uri = data.getData();
if (uri != null) {
LoggerUtils.d(TAG, "系统返回URI:" + uri.toString());
mUploadCallbackBelow.onReceiveValue(uri);
} else {
mUploadCallbackBelow.onReceiveValue(null);
}
} else {
// 以指定图像存储路径的方式调起相机,成功后返回data为空
LoggerUtils.d(TAG, "自定义结果:" + imageUri.toString());
mUploadCallbackBelow.onReceiveValue(imageUri);
}
} else {
mUploadCallbackBelow.onReceiveValue(null);
}
mUploadCallbackBelow = null;
}
/**
* Android API >= 21(Android 5.0) 版本的回调处理
*
* @param resultCode 选取文件或拍照的返回码
* @param data 选取文件或拍照的返回结果
*/
private void chooseAbove(int resultCode, Intent data) {
LoggerUtils.d(TAG, "返回调用方法--chooseAbove");
if (RESULT_OK == resultCode) {
updatePhotos();
if (data != null) {
// 这里是针对从文件中选图片的处理
Uri[] results;
Uri uriData = data.getData();
if (uriData != null) {
results = new Uri[]{uriData};
for (Uri uri : results) {
LoggerUtils.d(TAG, "系统返回URI:" + uri.toString());
}
mUploadCallbackAboveL.onReceiveValue(results);
} else {
mUploadCallbackAboveL.onReceiveValue(null);
}
} else {
LoggerUtils.d(TAG, "自定义结果:" + imageUri.toString());
mUploadCallbackAboveL.onReceiveValue(new Uri[]{imageUri});
}
} else {
mUploadCallbackAboveL.onReceiveValue(null);
}
mUploadCallbackAboveL = null;
}
private void updatePhotos() {
// 该广播即使多发(即选取照片成功时也发送)也没有关系,只是唤醒系统刷新媒体文件
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(imageUri);
sendBroadcast(intent);
}
}