Android 11 中如何创建目录存储PDF文件
Android 11 实现自定义目录存PDF的适配方案
问题根因
Android 11 强制启用分区存储机制,当应用的targetSdkVersion >=30时,android:requestLegacyExternalStorage="true" 配置会被系统完全忽略,不再兼容旧版全外部目录访问逻辑,直接通过File类操作公共目录会触发访问拒绝的报错。
正确实现路径
1. Manifest配置调整
给原有的legacy存储配置加上最高生效版本限制,避免不同系统版本的兼容冲突:
<application android:requestLegacyExternalStorage="true" android:maxSdkVersion="29"> </application>
这个配置仅在Android 10(SDK版本29)及以下系统生效,Android 11及以上会自动跳过该逻辑,走原生分区存储API流程。
2. 通过MediaStore完成公共目录的PDF保存
不需要申请高危的全文件管理权限,也不需要弹出SAF授权弹窗,直接通过系统提供的MediaStore API即可在公共目录下创建自定义文件夹、写入PDF文件:
// 构造PDF文件的存储参数 ContentValues pdfParams = new ContentValues(); // 定义PDF文件名 pdfParams.put(MediaStore.MediaColumns.DISPLAY_NAME, "生成的PDF文件.pdf"); // 定义PDF的MIME类型 pdfParams.put(MediaStore.MediaColumns.MIME_TYPE, "application/pdf"); // 定义自定义的保存路径,即公共Documents目录下的自定义子文件夹 pdfParams.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOCUMENTS + "/MyCustomPdfFolder"); // 向系统媒体库插入记录,获取可写入的文件Uri Uri pdfUri = getContentResolver().insert( MediaStore.Files.getContentUri("external"), pdfParams ); // 获取文件输出流,写入PDF内容 try (OutputStream pdfOut = getContentResolver().openOutputStream(pdfUri)) { // 在此处执行PDF内容的流写入操作 pdfOut.flush(); }
如果需要把PDF保存到公共下载目录,只需要把路径参数替换为Environment.DIRECTORY_DOWNLOADS + "/MyCustomPdfFolder"即可。
3. 权限适配说明
- Android 11、12 版本:不需要申请任何存储类权限,即可完成上述MediaStore的写入操作
- Android 10及以下版本:需要在Manifest中声明
WRITE_EXTERNAL_STORAGE权限,并完成对应动态权限申请 - 禁止为了适配该需求申请
MANAGE_EXTERNAL_STORAGE高危权限,容易导致应用上架审核被拒
常见避坑提示
- 不要直接通过
new File(公共目录路径/自定义子目录)的方式创建文件夹,Android 11上这类操作会直接抛出访问拒绝异常,是之前配置失效后报错的核心来源 - 写入完成的PDF文件可以直接在系统文件管理器的对应路径下被用户查看、分享
- 不需要做手动的目录创建逻辑,MediaStore会在写入文件时自动创建配置的子目录路径
内容的提问来源于stack exchange,提问作者Muhammad Asad
相关产品推荐
相关产品推荐

