安卓Adapter中点击PDF查看按钮报错:无法访问文件求解决
我来帮你排查这个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




