Flutter音乐播放器启动因权限崩溃,授权后正常,求解决方案
问题原因分析
崩溃的核心是权限请求的异步特性与媒体库读取逻辑的执行时机冲突:
- 你在
onInit中调用checkPermission(),但权限请求是异步操作——弹窗还未弹出、权限未授予时,on_audio_query插件已经尝试读取媒体库,触发java.lang.SecurityException(缺少READ_EXTERNAL_STORAGE权限)直接崩溃。 - 重启App时权限已被授予,所以能正常运行。
另外你的权限请求逻辑存在缺陷:递归调用checkPermission()可能导致无限循环,且未处理权限被永久拒绝的场景。
解决方案
1. 调整执行顺序:确保媒体读取在权限授予后执行
不要让媒体库读取逻辑自动初始化,而是等权限确认授予后再执行:
@override void onInit() { super.onInit(); // 确保UI初始化完成后再请求权限 WidgetsBinding.instance.addPostFrameCallback((_) async { await _checkAndRequestPermission(); // 权限通过后再加载歌曲 if (await Permission.storage.isGranted) { _loadMusicLibrary(); } }); } Future<void> _checkAndRequestPermission() async { var permStatus = await Permission.storage.status; if (!permStatus.isGranted) { permStatus = await Permission.storage.request(); // 处理不同权限状态 if (permStatus.isDenied) { // 可添加提示告知用户权限必要性,再重新请求 await _checkAndRequestPermission(); } else if (permStatus.isPermanentlyDenied) { // 引导用户到应用设置页手动开启权限 await openAppSettings(); } } } void _loadMusicLibrary() async { // 这里执行媒体库读取逻辑,比如调用on_audio_query的API // 示例: // List<SongModel> songs = await OnAudioQuery().querySongs(); // 后续处理歌曲数据 }
2. 适配Android版本权限
针对Android 13及以上系统,READ_EXTERNAL_STORAGE已被READ_MEDIA_AUDIO替代,需在AndroidManifest.xml中补充配置:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32"/> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
- 添加
android:maxSdkVersion="32"让旧权限仅在Android 12及以下生效,避免权限冗余。
3. 优化权限请求逻辑
去掉递归调用,改用清晰的状态判断,同时给用户明确的权限引导,避免无意义的重复请求。
内容的提问来源于stack exchange,提问作者amal
相关产品推荐
相关产品推荐

