Android 8中FileProvider Uri打开PDF显示空白问题求助
你碰到的这个问题是很典型的Android版本兼容性问题——在Android 7及以下能正常生成并打开的PDF,到了Android 8(API 26)就显示空白,但手动打开文件却完全正常。我来帮你拆解下核心原因和对应的解决方案:
核心原因分析
手动能打开说明PDF文件本身是正常的,问题出在FileProvider的配置/权限处理或者Android 8+对文件访问的 stricter 校验上,导致通过FileProvider共享时,第三方PDF阅读器无法正确读取文件内容。
分步解决方案
1. 检查FileProvider的路径配置
首先确认你的res/xml/file_paths.xml配置是否和PDF的实际存储路径匹配:
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 如果PDF存在内部存储的files/pdf目录下 --> <files-path name="pdf" path="pdf/"/> <!-- 如果存在外部存储的私有目录(比如getExternalFilesDir()下的pdf文件夹),用这个 --> <!-- <external-files-path name="pdf" path="pdf/"/> --> </paths>
Android 8+对FileProvider的路径匹配规则更严格,name是Uri中的别名,path是实际文件夹的相对路径,两者必须和你存储PDF的位置完全对应,否则会无法映射到真实文件。
2. 确保PDF文件完全写入磁盘
Android 8的文件系统缓存机制可能导致PdfDocument写入的数据没有立即同步到磁盘,FileProvider读取到的是空白缓存文件。解决方法是在写入后强制刷新输出流:
File pdfDir = new File(getFilesDir(), PDF_FOLDER); if (!pdfDir.exists()) { pdfDir.mkdirs(); // 确保存储目录存在 } File pdfFile = new File(pdfDir, "output.pdf"); PdfDocument document = new PdfDocument(); // ... 你的页面创建、Bitmap绘制逻辑 ... try (FileOutputStream fos = new FileOutputStream(pdfFile)) { document.writeTo(fos); fos.flush(); // 强制把缓存数据写入磁盘 } catch (IOException e) { e.printStackTrace(); } finally { document.close(); // 务必关闭PdfDocument释放资源 }
生成后可以打印pdfFile.length()检查文件大小,如果是0字节或者异常小,说明PDF生成过程本身有问题,要先排查绘制逻辑。
3. 正确授予临时访问权限
通过FileProvider共享文件时,必须给目标应用授予临时读取权限,Android 8+对这个权限的检查非常严格,缺失的话第三方阅读器会无法读取文件:
Uri pdfUri = FileProvider.getUriForFile(context, SHARED_PROVIDER_AUTHORITY, pdfFile); Intent viewIntent = new Intent(Intent.ACTION_VIEW); viewIntent.setDataAndType(pdfUri, "application/pdf"); viewIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // 关键:授予临时读取权限 viewIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); context.startActivity(viewIntent);
如果需要批量共享文件,可以用context.grantUriPermission()批量授权,但单个文件的话上面的方式就足够。
4. 验证PDF页面绘制逻辑
有时候空白是因为绘制内容超出了PDF页面范围,Android 8的PdfDocument对页面尺寸的处理可能和旧版本略有不同,确保页面尺寸和Bitmap匹配:
Bitmap bitmap = myCanvasView.getBitmap(); // 用Bitmap的真实宽高创建页面信息 PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(), bitmap.getHeight(), 1).create(); PdfDocument.Page page = document.startPage(pageInfo); Canvas canvas = page.getCanvas(); // 确保Bitmap绘制在页面范围内 canvas.drawBitmap(bitmap, 0, 0, null); document.finishPage(page);
如果Bitmap尺寸远大于页面尺寸,绘制内容会被截断,看起来就像空白。
最后排查步骤
如果以上方法都没用,可以试试:
- 清除应用缓存,重新生成PDF
- 用adb命令把PDF文件拉到电脑验证内容(比如
adb pull /data/data/你的包名/files/pdf/output.pdf)
内容的提问来源于stack exchange,提问作者Ricardo

