Android端下载MP3弹出音频应用列表如何实现直接保存为文件
结论
该需求完全可以实现。当前点击下载按钮后弹出音频应用选择列表,并非下载逻辑本身的问题,是你代码中主动加入的「下载完成后打开文件」逻辑触发的系统行为。
问题原因
你现有代码在Dio下载完成后执行了这行逻辑:
OpenFile.open("${dir.path}/$fileName", type: 'audio/mpeg');
该方法会向系统发起打开MP3音频文件的请求,系统会检索所有注册了音频类型处理能力的应用(Spotify、VLC、系统自带音乐播放器等),当存在多个可处理该类型文件的应用时,就会弹出选择列表。如果仅需要将文件保存到本地、不需要下载完成后自动打开,直接删除这行代码即可,不会再弹出应用选择窗口。
现有代码的Android端兼容性修正
你当前的实现还有两个Android平台适配问题,会导致部分机型下载失败、用户无法在本地找到下载的文件:
- 权限适配错误:
Permission.storage在Android 13(API 33)及以上版本已被废弃,该版本起系统对存储权限做了细分,应用写入公共下载目录在Android 10及以上版本不需要申请任何存储权限,仅Android 9及以下版本需要申请存储写入权限。 - 存储路径不合理:
getApplicationDocumentsDirectory()获取的是应用沙盒私有目录,用户无法通过系统文件管理器直接访问该目录下的文件,如果要让用户能直接在本地找到下载的MP3,需要将文件存储到系统公共下载目录。
修正后的参考代码
首先确认pubspec.yaml中引入所需依赖:
dependencies: dio: ^稳定版 permission_handler: ^稳定版 path_provider: ^稳定版 device_info_plus: ^稳定版 # 用于获取系统版本做权限适配
修正后的MobileDownloadService实现:
import 'dart:io'; import 'package:dio/dio.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:path_provider/path_provider.dart'; import 'package:device_info_plus/device_info_plus.dart'; class MobileDownloadService { Future<void> download({required String url, required String fileName}) async { // 校验下载权限 bool hasPermission = await _checkRequiredPermission(); if (!hasPermission) return; // 获取存储路径:Android存公共下载目录,iOS存应用文档目录 Directory saveDir; if (Platform.isAndroid) { saveDir = (await getExternalStoragePublicDirectory(StorageDirectory.downloads))!; } else { saveDir = await getApplicationDocumentsDirectory(); } String savePath = '${saveDir.path}/$fileName'; // 执行文件下载 Dio dio = Dio(); await dio.download( url, savePath, onReceiveProgress: (int received, int total) { // 可在此处实现下载进度更新逻辑 }, ); // 已删除原OpenFile.open调用,不会再弹出应用选择窗 // 可在此处触发UI提示,告知用户文件已保存至下载目录 } Future<bool> _checkRequiredPermission() async { if (!Platform.isAndroid) return true; AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo; int sdkInt = androidInfo.version.sdkInt; // Android 10(API 29)及以上写入公共下载目录无需权限 if (sdkInt >= 29) return true; // Android 9及以下申请存储写入权限 PermissionStatus status = await Permission.storage.request(); return status.isGranted; } }
另外需要在AndroidManifest.xml的application标签下补充配置,兼容Android 10以下版本的存储访问:
<application android:requestLegacyExternalStorage="true" ...其他配置> ... </application>
内容的提问来源于stack exchange,提问作者whitebear
相关产品推荐
相关产品推荐

