You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity Android API23及以上版本如何调用PDF阅读器打开PDF文件

解决API23+设备打开PDF的问题

我之前帮不少开发者处理过这个问题,核心原因是Android 6.0(API23)之后的权限机制和文件访问限制发生了关键变化,尤其是API24开始的FileUriExposedException限制,直接导致旧的file:// Uri方式无法正常工作。下面给你一步步的解决方案:

为什么原来的方法失效?

从Android 6.0(API23)开始,系统引入了运行时权限机制,读取外部存储需要动态申请权限;而从Android 7.0(API24)开始,直接通过file:// Uri分享应用私有文件给其他应用会触发安全异常,系统禁止这种不安全的跨应用文件访问方式,所以你的Application.OpenUrl("file://" + path)就失效了。

解决方案:用FileProvider实现安全的文件共享

下面是完整的实现步骤:

1. 在AndroidManifest.xml中注册FileProvider

在<application>标签内添加FileProvider的配置,它是Android提供的安全共享文件的组件:

<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>

注意:如果你用的是旧版support库,把androidx.core.content.FileProvider换成android.support.v4.content.FileProvider;authorities建议用你的应用ID加上.fileprovider,避免和其他应用冲突。

2. 创建文件路径配置文件

在res/xml目录下新建file_paths.xml文件(如果xml目录不存在就手动创建),用来定义允许共享的文件目录:

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 共享应用内部存储的文件 -->
    <files-path name="internal_files" path="." />
    <!-- 共享应用专属外部存储的文件 -->
    <external-files-path name="external_files" path="." />
    <!-- 共享外部公共目录的文件(比如SD卡根目录) -->
    <external-path name="external_public" path="." />
</paths>

按需选择对应的路径标签:

  • files-path对应应用内部存储的/data/data/[你的应用ID]/files/目录
  • external-files-path对应外部存储的Android/data/[你的应用ID]/files/目录
  • external-path对应外部存储的根目录

3. 动态申请存储权限(如果文件在外部存储)

如果你的PDF文件存放在外部存储(比如SD卡),API23及以上需要动态申请READ_EXTERNAL_STORAGE权限:

// 检查权限是否已授予
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
    // 申请权限
    ActivityCompat.requestPermissions(this,
            new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            1001);
} else {
    // 权限已授予,直接打开PDF
    openPdfFile(pdfFile);
}

// 处理权限申请结果
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 1001) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            openPdfFile(pdfFile);
        } else {
            Toast.makeText(this, "需要存储权限才能打开PDF文件", Toast.LENGTH_SHORT).show();
        }
    }
}

4. 生成安全的Content Uri并打开PDF

编写openPdfFile方法,根据系统版本选择Uri生成方式,然后启动Intent打开PDF:

private void openPdfFile(File pdfFile) {
    Uri pdfUri;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        // API24及以上,用FileProvider生成安全的Content Uri
        pdfUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", pdfFile);
    } else {
        // API23及以下,直接用file:// Uri(注意权限问题)
        pdfUri = Uri.fromFile(pdfFile);
    }

    // 构建打开PDF的Intent
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(pdfUri, "application/pdf");
    // 授予临时读取权限给目标应用
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    // 确保有应用能处理这个Intent
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    } else {
        Toast.makeText(this, "未找到可打开PDF的应用", Toast.LENGTH_SHORT).show();
    }
}

额外注意事项

  • 确保你的PDF文件路径正确,文件存在且具备可读权限
  • 如果是Unity等跨平台框架调用,需要把上述Java代码封装成Android插件,或者用框架提供的Android交互API调用对应方法
  • 测试时重点验证Android 7.0及以上设备,避免触发FileUriExposedException

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:55:05