Flutter读取非应用创建CSV文件时遇权限拒绝错误求助
解决方案:Flutter读取其他应用创建的CSV文件权限被拒问题
问题根源
Android 10(API 29)及以上版本启用了Scoped Storage机制,Permission.storage权限仅允许你的应用访问自己创建的文件,无法直接读取其他应用生成的公共目录(比如Download)下的文件,这就是你遇到权限拒绝的原因。
两种解决办法
方法一:使用文件选择器(推荐,符合Google应用规范)
通过让用户手动选择文件的方式绕过Scoped Storage限制,不需要额外的特殊权限,步骤如下:
- 添加
file_picker依赖到pubspec.yaml:
dependencies: file_picker: ^6.1.1
- 修改你的
restore函数,替换硬编码路径为文件选择器获取:
Future<void> restore() async { // 无需再申请Permission.storage final result = await FilePicker.platform.pickFiles( type: FileType.custom, allowedExtensions: ['csv'], ); if (result != null) { final filePath = result.files.single.path!; final Database db = await SQLHelper.db(); await db.delete("spendinfo"); final File f = File(filePath); final List<List<dynamic>> csvData = CsvToListConverter().convert(await f.readAsString()); final List<spendinfo> lastList = csvData.map((csvRow) => spendinfo.fromCVSObjetct(csvRow)).toList(); for (var item in lastList) { await SQLHelper.createItem(item); print(item.id); } } }
方法二:申请MANAGE_EXTERNAL_STORAGE权限(仅特殊场景使用)
这个权限允许应用访问所有外部存储文件,但Google Play可能会拒绝非必要使用该权限的应用上架,步骤如下:
- 在
android/app/src/main/AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- 修改权限申请逻辑:
import 'package:device_info_plus/device_info_plus.dart'; Future<void> restore() async { PermissionStatus permissionStatus; if (Platform.isAndroid) { final androidInfo = await DeviceInfoPlugin().androidInfo; if (androidInfo.version.sdkInt >= 30) { permissionStatus = await Permission.manageExternalStorage.request(); } else { permissionStatus = await Permission.storage.request(); } } else { permissionStatus = await Permission.storage.request(); } if (permissionStatus == PermissionStatus.granted) { // 原有读取逻辑保持不变 final Database db = await SQLHelper.db(); await db.delete("spendinfo"); final fileName = "Bka_data.cvs"; var path = await ExternalPath.getExternalStoragePublicDirectory(ExternalPath.DIRECTORY_DOWNLOADS); final directory = "$path/$fileName"; final File f = File(directory); final List<List<dynamic>> csvData = CsvToListConverter().convert(await f.readAsString()); final List<spendinfo> lastList = csvData.map((csvRow) => spendinfo.fromCVSObjetct(csvRow)).toList(); for (var i = 0; i < lastList.length; i++) { SQLHelper.createItem(lastList[i]); print(lastList[i].id); } } }
补充提示
- 注意你代码里的文件名拼写:
Bka_data.cvs应为Bka_data.csv(后缀是csv而非cvs),避免因文件名错误引发的额外问题。 - 方法一的文件选择器更符合Android存储规范,建议优先使用,规避应用上架风险。
内容的提问来源于stack exchange,提问作者ibrahim ethem
相关产品推荐
相关产品推荐

