Android WebView中img标签如何显示SD卡图片?问题求助
解决WebView中无法显示SD卡图片URI的问题
以下是几个可行的解决方案,按优先级排序:
方案1:使用FileProvider生成content://格式的URI(推荐)
从Android 7.0开始,直接使用file:// URI会触发FileUriExposedException,且WebView对file://资源的访问有严格权限限制,改用content://格式的URI可以彻底解决这类问题。
步骤1:配置FileProvider
在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>
步骤2:创建文件路径配置
在res/xml目录下新建file_paths.xml,定义允许共享的文件路径(示例为SD卡DCIM目录,可根据实际存储路径调整):
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="camera_photos" path="DCIM/" /> <!-- 若需共享整个外部存储,可替换为: <external-path name="external_storage" path="." /> --> </paths>
步骤3:生成content URI并传递给JS
修改拍照逻辑,用FileProvider生成合规的URI:
// 先创建目标图片文件 File imageFile = new File(mActivity.getExternalFilesDir(Environment.DIRECTORY_DCIM), "photo_" + System.currentTimeMillis() + ".jpg"); // 生成content://格式的URI imgUri = FileProvider.getUriForFile(mActivity, mActivity.getPackageName() + ".fileprovider", imageFile); // 保留原有拍照回调逻辑,传递的URI已为合规格式 mCaramerLauncher = mActivity.registerForActivityResult(new ActivityResultContracts.TakePicture(), new ActivityResultCallback<Boolean>() { @Override public void onActivityResult(Boolean result) { JsonObject rsJson = new JsonObject(); if(result){ rsJson.addProperty("uri", imgUri.toString()); // 现在是content://开头的URI rsJson.addProperty("code", 0); }else{ rsJson.addProperty("data", ""); rsJson.addProperty("code", 1); } jsCallParam.mCallback.callback(baseTMFWeb, rsJson.toString()); } });
方案2:将图片转为Base64字符串传递给JS
如果不想配置FileProvider,可以直接把图片转为Base64字符串,让HTML通过data URI加载:
修改拍照回调代码:
mCaramerLauncher = mActivity.registerForActivityResult(new ActivityResultContracts.TakePicture(), new ActivityResultCallback<Boolean>() { @Override public void onActivityResult(Boolean result) { JsonObject rsJson = new JsonObject(); if(result){ try { // 读取图片文件为字节数组 File imageFile = new File(imgUri.getPath()); FileInputStream fis = new FileInputStream(imageFile); byte[] bytes = new byte[(int) imageFile.length()]; fis.read(bytes); fis.close(); // 转为Base64格式的图片数据 String base64Img = Base64.encodeToString(bytes, Base64.DEFAULT); rsJson.addProperty("imgData", "data:image/jpeg;base64," + base64Img); rsJson.addProperty("code", 0); } catch (IOException e) { e.printStackTrace(); rsJson.addProperty("code", 1); rsJson.addProperty("msg", "图片读取失败"); } }else{ rsJson.addProperty("data", ""); rsJson.addProperty("code", 1); } jsCallParam.mCallback.callback(baseTMFWeb, rsJson.toString()); } });
在HTML中直接使用该Base64字符串作为img的src:
<img src="data:image/jpeg;base64,xxx" />
方案3:Android 10及以下临时兼容(不推荐)
若应用仅兼容Android 10(API 29)及以下版本,可尝试添加以下WebSettings配置,但该方式在Android 11+已被废弃且存在安全风险:
webSettings.setAllowFileAccessFromFileURLs(true); webSettings.setAllowUniversalAccessFromFileURLs(true);
内容的提问来源于stack exchange,提问作者ddd54321
相关产品推荐
相关产品推荐

