Flutter保存PDF触发PathAccessException权限拒绝问题求助
解决Flutter保存PDF到外部存储的权限拒绝问题
问题根源
你的错误是因为Android 13(API 33+)废弃了传统的WRITE_EXTERNAL_STORAGE/READ_EXTERNAL_STORAGE权限,常规的Permission.storage请求在Android 13+仅授予媒体文件的读取权限,无法写入到用户选择的任意公共目录。
解决方案
1. 更新AndroidManifest.xml权限配置
在android/app/src/main/AndroidManifest.xml中添加兼容新旧版本的权限:
<!-- 兼容Android 12及以下版本 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> <!-- Android 13+ 所需的全存储管理权限 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
2. 添加设备信息依赖
需要获取Android SDK版本来判断权限类型,在pubspec.yaml中添加:
dependencies: device_info_plus: ^9.1.0 # 使用最新稳定版本
执行flutter pub get安装依赖。
3. 修改权限请求与保存逻辑
替换原按钮点击事件中的权限处理代码,根据Android版本请求对应权限:
onButtonPressed: () async { final pdf = pw.Document(); final font = await rootBundle.load("assets/Roboto/Roboto-Black.ttf"); final ttf = pw.Font.ttf(font); pdf.addPage(pw.Page( pageFormat: PdfPageFormat.a4, build: (pw.Context context) { return pw.Center( child: pw.Text('Dart is awesome', style: pw.TextStyle(font: ttf, fontSize: 40)), ); }, )); bool hasPermission = false; if (Platform.isAndroid) { final androidInfo = await DeviceInfoPlugin().androidInfo; if (androidInfo.version.sdkInt >= 33) { // Android 13+ 请求全存储管理权限 final status = await Permission.manageExternalStorage.request(); if (status.isGranted) { hasPermission = true; } else if (status.isDenied || status.isPermanentlyDenied) { // 引导用户到应用设置手动开启权限 await openAppSettings(); return; } } else { // Android 12及以下请求传统存储权限 final status = await Permission.storage.request(); hasPermission = status.isGranted; } } else { // 其他平台直接请求存储权限 final status = await Permission.storage.request(); hasPermission = status.isGranted; } if (hasPermission) { final directoryPath = await FilePicker.platform.getDirectoryPath(); if (directoryPath != null) { final filePath = path.join(directoryPath, 'example.pdf'); final file = File(filePath); await file.writeAsBytes(await pdf.save()); print('PDF saved to $filePath'); } else { print('No folder selected'); } } else { print('Permission denied'); } },
替代方案:无需全存储权限的固定目录保存
如果不需要用户选择任意文件夹,仅需保存到系统默认的Downloads目录,可以使用path_provider包,无需申请MANAGE_EXTERNAL_STORAGE权限:
- 添加依赖:
dependencies: path_provider: ^2.1.1
- 修改保存逻辑:
if (hasPermission) { final downloadsDir = await getDownloadsDirectory(); if (downloadsDir != null) { final filePath = path.join(downloadsDir.path, 'example.pdf'); final file = File(filePath); await file.writeAsBytes(await pdf.save()); print('PDF saved to $filePath'); } }
注意事项
MANAGE_EXTERNAL_STORAGE权限属于特殊权限,Google Play可能会对使用该权限的应用进行审核,仅当应用确实需要访问任意文件目录时才使用。- 测试时需卸载旧版本应用后重新安装,否则权限配置可能不生效。
内容的提问来源于stack exchange,提问作者Abhishek Tiwari
相关产品推荐
相关产品推荐

