如何调用grantUriPermissions为ACTION_VIEW的引用文件授予Uri权限
解决方案
方案1:通过ClipData批量附加目录内所有资源URI(合规推荐,无需解析HTML)
该方案利用Android系统原生特性:Intent附加的ClipData内包含的所有URI,都会自动被授予Intent上设置的读写权限,无需手动逐个授权,也不需要解析HTML内容判断引用的资源。
实现步骤:
- 当检测到要打开的是
.html类型文件时,获取该HTML文件所在的父目录 - 遍历父目录下的所有文件(可按需调整遍历的子目录深度),生成对应的FileProvider URI
- 把所有URI构造为ClipData附加到Intent上,系统会自动完成批量授权
代码示例:
// 原有Intent构造逻辑不变 Intent deflt = new Intent(); deflt.setAction(android.content.Intent.ACTION_VIEW); deflt.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); deflt.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); deflt.setDataAndType(uri, mime); // 仅针对HTML文件增加批量授权逻辑 if ("text/html".equals(mime)) { File htmlFile = new File(本地HTML文件的绝对路径); File parentDir = htmlFile.getParentFile(); List<Uri> allResUris = new ArrayList<>(); // 遍历目录下所有文件生成URI traverseResDir(parentDir, allResUris); // 构造ClipData附加到Intent if (!allResUris.isEmpty()) { ClipData clipData = ClipData.newRawUri(null, allResUris.get(0)); for (int i = 1; i < allResUris.size(); i++) { clipData.addItem(new ClipData.Item(allResUris.get(i))); } deflt.setClipData(clipData); } } startActivity(deflt);
对应的目录遍历方法:
private void traverseResDir(File dir, List<Uri> uriList) { File[] files = dir.listFiles(); if (files == null) return; for (File file : files) { if (file.isDirectory()) { traverseResDir(file, uriList); } else { // 可在此处增加后缀过滤,仅添加图片、CSS、JS等资源文件减少开销 Uri resUri = FileProvider.getUriForFile(this, "你的FileProvider授权标识", file); uriList.add(resUri); } } }
该方案完全符合Android权限规范,兼容性覆盖Android 4.4及以上系统,只要HTML引用的资源都在同级目录下就可以正常加载。
方案2:临时禁用FileUri暴露检查(最简方案,适合快速实现)
如果不需要严格遵循Android官方规范,可直接使用file://格式URI传递,跳过FileProvider的权限限制,浏览器可以直接访问同目录下所有本地文件,不需要额外授权逻辑。
仅需要在Application或者启动页Activity的onCreate方法中添加一行代码禁用暴露检查:
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().build());
之后构造Intent的时候直接传递原生文件URI即可:
deflt.setDataAndType(Uri.fromFile(htmlFile), "text/html");
注意:该方案不符合Android 7.0之后的官方开发规范,仅适合个人开发或内部使用的应用,正式上线应用不推荐使用。
内容的提问来源于stack exchange,提问作者Luis A. Florit
相关产品推荐
相关产品推荐

