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

安卓Adapter中点击PDF查看按钮报错:无法访问文件求解决

解决PDF打开报错:"This file could not be accessed Check the location or the network and try again"

我来帮你排查这个PDF打开失败的问题,咱们从几个核心点入手分析:

1. 先确认文件路径是否正确

你代码里用Environment.getExternalStorageDirectory()加上opportunity.getPdf_link()来构建文件路径,这里很容易踩坑:

  • 如果opportunity.getPdf_link()返回的是完整文件路径(比如/storage/emulated/0/Documents/test.pdf),那拼接后就会变成重复路径,肯定找不到文件。
  • 建议你加个日志打印实际路径,确认文件是否真的存在:
    Log.d("PDF_DEBUG", "文件路径:" + file.getAbsolutePath() + ",是否存在:" + file.exists());
    
  • 如果PDF是存在系统Download目录,应该用Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)来替代根目录,更符合Android规范。

2. Android 10+的分区存储限制

从Android 10(API 29)开始,系统默认启用分区存储,直接访问Environment.getExternalStorageDirectory()会被限制。如果你的应用targetSdkVersion >=29,可以先临时兼容:
AndroidManifest.xml<application>标签里添加:

android:requestLegacyExternalStorage="true"

后续建议逐步适配MediaStore或者应用私有目录来存储文件,避免依赖这个临时兼容方案。

3. FileProvider的paths配置是否正确

你的Manifest里配置了FileProvider,但@xml/provider_paths的内容直接决定了它能访问哪些目录。如果PDF在外部存储根目录,你的provider_paths.xml应该这样写:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 允许访问外部存储根目录 -->
    <external-path name="external_root" path="."/>
</paths>

如果PDF在Download目录,就改用<external-public-path>

<external-public-path name="downloads" path="Download"/>

4. 权限申请是否完整

虽然你在Manifest里加了读写权限,但从Android 6.0(API 23)开始,危险权限需要动态申请,不能只靠Manifest声明。在打开PDF前,必须先检查并申请READ_EXTERNAL_STORAGE权限(Android 13+需要READ_MEDIA_DOCUMENTS):

if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    if (mContext instanceof Activity) {
        ActivityCompat.requestPermissions((Activity) mContext, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 100);
    }
    return;
}

5. Intent的Flags设置问题

你代码里用setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)会覆盖之前添加的FLAG_GRANT_READ_URI_PERMISSION,导致权限失效。应该用addFlags()来添加多个Flags:

pdfOpenintent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_TOP);

修正后的完整代码示例

holder.pdf.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 1. 先检查权限
        if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            if (mContext instanceof Activity) {
                ActivityCompat.requestPermissions((Activity) mContext, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 100);
            }
            Toast.makeText(mContext, "请先授予存储权限", Toast.LENGTH_SHORT).show();
            return;
        }

        // 2. 构建正确的文件路径(假设PDF存放在Download目录,getPdf_link()返回文件名)
        File pdfFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), opportunity.getPdf_link());
        
        // 3. 检查文件是否存在
        if (!pdfFile.exists()) {
            Toast.makeText(mContext, "文件不存在,请确认下载路径", Toast.LENGTH_SHORT).show();
            Log.d("PDF_ERROR", "文件不存在:" + pdfFile.getAbsolutePath());
            return;
        }

        // 4. 获取FileProvider的Uri
        Uri pdfUri = FileProvider.getUriForFile(mContext, mContext.getPackageName() + ".provider", pdfFile);
        
        // 5. 构建打开PDF的Intent
        Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
        pdfIntent.setDataAndType(pdfUri, "application/pdf");
        pdfIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_TOP);

        // 6. 启动Activity
        try {
            mContext.startActivity(pdfIntent);
        } catch (ActivityNotFoundException e) {
            Toast.makeText(mContext, "未找到可打开PDF的应用,请先安装", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
    }
});

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

火山引擎 最新活动