Android应用无法向外部存储Download文件夹写入生成的PDF文件问题求解
安卓外部存储生成PDF失败问题解决方案
问题根因
- 动态权限缺失:Android 6.0(API 23)及以上系统,存储类权限仅在Manifest中声明无效,必须主动触发动态申请流程由用户授权,你当前的代码只做了权限校验,没有申请逻辑,所以
checkSelfPermission返回PERMISSION_DENIED(值为-1)。 - 权限规则过时:你的targetSdk版本为31(对应Android 12),
WRITE_EXTERNAL_STORAGE权限在Android 10(API 29)及以上版本已经被官方废弃,即便申请也不会获得授权。 - 路径规则变更:你使用的
Environment.getExternalStorageDirectory()在API 29及以上已被禁止直接访问,无法在外部存储根目录自建文件夹写入文件。
修复步骤
- 修改
AndroidManifest.xml配置
在<application>节点中添加过渡适配属性,临时兼容旧存储逻辑:
android:requestLegacyExternalStorage="true"
如果你的应用不需要访问其他应用的私有文件,仅需要写入公共Download目录,可以删除Manifest中WRITE_EXTERNAL_STORAGE的声明,API 30+写入公共媒体/下载目录不需要该权限。
2. 补充动态权限申请逻辑
在onCreate方法中增加权限校验和申请逻辑,适配Android 6.0-Android 9的设备。
3. 调整存储路径
不要在外部存储根目录自建文件夹,改为写入系统公共Download目录,符合系统存储规范。
核心修改代码示例
动态权限申请代码(添加到onCreate方法中)
// 存储权限申请请求码 private static final int REQUEST_STORAGE_PERMISSION = 1001; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_save_path); Button btnShowPath = findViewById(R.id.btnPath); // 先校验权限,未授权则申请 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_STORAGE_PERMISSION); btnShowPath.setEnabled(false); } btnShowPath.setOnClickListener(v -> { try { writeFile(); } catch (FileNotFoundException e) { e.printStackTrace(); } }); } // 接收权限申请结果 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_STORAGE_PERMISSION) { Button btnShowPath = findViewById(R.id.btnPath); btnShowPath.setEnabled(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED); } }
writeFile方法路径修改
public void writeFile() throws FileNotFoundException { if (isExternalStorageWritable()) { // 改为写入系统公共Download目录 File dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS); File file = new File(dir, "newFile.pdf"); FileOutputStream fOut = new FileOutputStream(file); // 后面的PDF生成逻辑保持不变即可 Rectangle layout = new Rectangle(PageSize.ARCH_A); layout.setBorderColor(BaseColor.DARK_GRAY); layout.setBorderWidth(6); layout.setBorder(Rectangle.BOX); Document document = new Document(layout); PdfWriter writer = null; try { writer = PdfWriter.getInstance(document, fOut); document.open(); PdfContentByte cb = writer.getDirectContent(); float pdfPageWidth = document.getPageSize().getWidth(); float pdfPageHeight = document.getPageSize().getHeight(); document.add(new Paragraph("pdfPageWidth = "+pdfPageWidth)); document.add(new Paragraph("pdfPageHeight = "+pdfPageHeight)); Barcode39 barcode39 = new Barcode39(); barcode39.setCode("123456789"); Image code39Image = barcode39.createImageWithBarcode(cb, null, null); document.add(code39Image); document.newPage(); document.close(); } catch (DocumentException e) { e.printStackTrace(); } } else { Toast.makeText(getApplicationContext(), "无法访问外部存储", Toast.LENGTH_SHORT).show(); } }
内容的提问来源于stack exchange,提问作者Scripta14
相关产品推荐
相关产品推荐

