You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android 11应用内PDF下载与预览功能权限异常问题求助

解决Android 11上PDF下载后无法打开的权限问题

你碰到的这个问题,本质是Android 11(API 30)引入的分区存储机制在限制文件访问——哪怕你用了应用的外部缓存目录(externalCacheDir),直接用file:// Uri把文件分享给PDF查看器也会被系统拦截,因为第三方应用没有权限访问你的应用私有目录。下面是一步步的解决方案:

核心问题拆解

Android 11启用分区存储后,READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE权限的作用范围被大幅缩小,而且其他应用无法通过file:// Uri直接访问你的应用私有文件(包括externalCacheDir里的文件),这就是你看到EACCES (Permission denied)错误的根本原因。

解决方案:用FileProvider安全分享文件

FileProvider是Android官方提供的内容提供者,能安全地把你的应用私有文件授权给其他应用访问,具体步骤如下:

1. 在AndroidManifest中注册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>

⚠️ 注意:authorities必须用你的应用包名加上.fileprovider,保证唯一性,比如你的包名是com.example.myapp,那这里就填com.example.myapp.fileprovider

2. 创建file_paths.xml资源文件

res/xml/目录下新建file_paths.xml(如果xml目录不存在就手动创建),内容如下:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 配置允许分享应用外部缓存目录下的所有文件 -->
    <external-cache-path name="external_cache" path="." />
</paths>

这个文件告诉FileProvider,你要分享的文件位于应用的外部缓存目录。

3. 修改代码中的Intent逻辑

把原来生成file:// Uri的代码替换成FileProvider生成的Content Uri,同时给Intent添加临时读取权限:

val int = Intent(Intent.ACTION_VIEW).apply {
    // 用FileProvider生成合法的Content Uri
    val contentUri = FileProvider.getUriForFile(
        a,
        "${app.packageName}.fileprovider", // 和Manifest里的authorities保持一致
        r
    )
    setDataAndType(contentUri, "application/pdf")
    // 授予PDF查看器临时读取该文件的权限
    addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivityForResult(int, 1)

4. 优化权限声明(可选)

因为你用的是应用私有目录(externalCacheDir),实际上在Android 10+系统中不需要申请READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE权限。如果你的targetSdkVersion是30+,可以给这两个权限加上maxSdkVersion,避免不必要的权限申请:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="29"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29"/>

额外提醒

  • 确保你的项目使用AndroidX库,这样才能正常引用androidx.core.content.FileProvider;如果还用旧的Support库,就换成android.support.v4.content.FileProvider
  • 大部分主流PDF查看器(比如Google PDF Viewer)都支持通过Content Uri访问文件,测试时可以优先用这些应用验证。

这样修改后,Android 11设备上就能正常打开下载的PDF文件了,同时也符合Android最新的存储规范。

内容的提问来源于stack exchange,提问作者Martin

火山引擎 最新活动