Flutter Dio真机无下载文件但模拟器正常问题求助
解决Flutter Dio在安卓真机下载文件到Download目录不显示的问题
问题原因分析
你遇到的问题核心出在三点:
- Android 10(API 29)及以上存储权限机制变更,直接写入公共Download目录的权限逻辑发生了变化
- 文件下载完成后未触发系统媒体扫描,导致文件管理器无法立即识别到新文件
- 硬编码路径
/storage/emulated/0/Download在部分真机上存在兼容性问题
解决方案步骤
1. 替换硬编码路径,用官方API获取公共Download目录
不要直接写死路径,通过path_provider库获取标准的公共下载目录,确保在不同设备上都能正确定位。
先在pubspec.yaml添加依赖:
dependencies: path_provider: ^2.1.1
2. 适配Android 10+的存储权限
Android 10及以上,针对公共媒体目录的写入,需要在AndroidManifest.xml中添加兼容配置;Android 13+则需要申请MANAGE_EXTERNAL_STORAGE权限(需引导用户去系统设置开启)。
在android/app/src/main/AndroidManifest.xml的<application>标签内添加:
android:requestLegacyExternalStorage="true"
3. 下载完成后触发媒体扫描
文件写入公共目录后,必须通知系统媒体库扫描该文件,才能让文件管理器显示出来。可以借助media_scanner库实现。
添加media_scanner依赖:
dependencies: media_scanner: ^1.0.1
修改后的完整代码
onPressed: () async { // 适配不同Android版本的权限 Permission permission; if (Platform.isAndroid) { final androidInfo = await DeviceInfoPlugin().androidInfo; if (androidInfo.version.sdkInt >= 33) { permission = Permission.manageExternalStorage; } else { permission = Permission.storage; } } else { permission = Permission.storage; } PermissionStatus status = await permission.request(); if (status.isGranted) { // 获取公共Download目录 Directory? dir; if (Platform.isAndroid) { dir = await getExternalStoragePublicDirectory(DirectoryDownloads); } else if (Platform.isIOS) { dir = await getApplicationDocumentsDirectory(); } if (dir == null) { print("无法获取下载目录"); return; } String savename = "file.gpx"; String savePath = "${dir.path}/$savename"; print(savePath); try { await Dio().download(fileurl, savePath, onReceiveProgress: (received, total) { if (total != -1) { print("${(received / total * 100).toStringAsFixed(0)}%"); } }); print("File is saved to download folder."); // 触发媒体扫描,让文件在文件管理器中显示 if (Platform.isAndroid) { await MediaScanner.loadMedia(savePath); } } on DioError catch (e) { print(e.message); print(e.response?.data); // 打印更详细的错误信息便于排查 } } else { print("No permission to read and write."); // Android 13+权限被拒时,引导用户去设置开启 if (Platform.isAndroid && await DeviceInfoPlugin().androidInfo.version.sdkInt >= 33) { await openAppSettings(); } } }
额外注意事项
- 测试时可先通过
adb shell或应用内读取文件的方式,确认文件是否真的下载成功,避免误以为下载失败 - Android 14及后续版本可能有更严格的权限限制,需及时跟进官方文档更新
- 如果不需要在应用外部访问文件,建议使用应用专属目录,无需特殊权限,路径可通过
getExternalStorageDirectory()获取
内容的提问来源于stack exchange,提问作者Jorgen Timarey
相关产品推荐
相关产品推荐

