Android WebView实现拍照或本地存储选图的方案咨询
Android WebView 实现拍照/本地存储选图功能
要让WebView的文件选择支持拍照和本地选图,你需要自定义Intent,将拍照动作和文件选择动作整合到选择器中,同时处理拍照后的Uri返回。以下是修改后的完整代码:
1. 修改onShowFileChooser方法
private ValueCallback<Uri[]> uploadMessage; private static final int REQUEST_SELECT_FILE = 100; private Uri cameraImageUri; // 保存拍照生成的图片Uri public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) { if (uploadMessage != null) { uploadMessage.onReceiveValue(null); uploadMessage = null; } uploadMessage = filePathCallback; // 1. 创建拍照Intent Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (takePhotoIntent.resolveActivity(getPackageManager()) != null) { // 创建拍照后保存的文件 File photoFile = null; try { photoFile = createImageFile(); } catch (IOException ex) { ex.printStackTrace(); } if (photoFile != null) { // Android 7.0及以上用FileProvider获取Uri if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { cameraImageUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile); } else { cameraImageUri = Uri.fromFile(photoFile); } takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraImageUri); } } // 2. 创建本地文件选择Intent Intent pickFileIntent = new Intent(Intent.ACTION_GET_CONTENT); pickFileIntent.setType("image/*"); pickFileIntent.addCategory(Intent.CATEGORY_OPENABLE); // 3. 整合两个Intent到选择器 Intent[] intentArray; if (takePhotoIntent != null) { intentArray = new Intent[]{takePhotoIntent}; } else { intentArray = new Intent[0]; } Intent chooserIntent = new Intent(Intent.ACTION_CHOOSER); chooserIntent.putExtra(Intent.EXTRA_INTENT, pickFileIntent); chooserIntent.putExtra(Intent.EXTRA_TITLE, "选择图片来源"); chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, intentArray); try { startActivityForResult(chooserIntent, REQUEST_SELECT_FILE); } catch (ActivityNotFoundException e) { uploadMessage = null; return false; } return true; } // 辅助方法:创建拍照保存的临时文件 private File createImageFile() throws IOException { String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); String imageFileName = "JPEG_" + timeStamp + "_"; File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES); return File.createTempFile( imageFileName, /* 前缀 */ ".jpg", /* 后缀 */ storageDir /* 存储目录 */ ); }
2. 实现onActivityResult方法处理返回结果
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_SELECT_FILE) { if (uploadMessage == null) return; Uri[] results = null; // 处理拍照结果 if (resultCode == RESULT_OK && cameraImageUri != null) { results = new Uri[]{cameraImageUri}; } // 处理本地选图结果 else if (resultCode == RESULT_OK && data != null) { String dataString = data.getDataString(); if (dataString != null) { results = new Uri[]{Uri.parse(dataString)}; } } uploadMessage.onReceiveValue(results); uploadMessage = null; cameraImageUri = null; // 重置拍照Uri } }
3. 必要配置(Android 7.0+)
- 在
AndroidManifest.xml中注册FileProvider:
<application> ... <provider android:name="androidx.core.content.FileProvider" android:authorities="${applicationId}.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> </application>
- 在
res/xml目录下创建file_paths.xml文件:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="my_images" path="Pictures" /> </paths>
关键说明
- 通过
Intent.createChooser将拍照和文件选择的Intent合并,让用户选择来源。 - 拍照时需要创建临时文件,并通过FileProvider(Android 7.0+)获取安全Uri,避免Uri暴露异常。
- 在
onActivityResult中区分拍照和选图的结果,将正确的Uri传递给WebView的uploadMessage。
内容的提问来源于stack exchange,提问作者Meow
相关产品推荐
相关产品推荐

