Flutter中audioQuery.querySongs()未等待权限授权致崩溃求助
解决audioQuery.querySongs()在权限授予前执行导致的崩溃问题
问题背景
使用audioQuery开发Flutter音乐应用时,audioQuery.querySongs()会在用户完成存储权限授权前提前执行,直接导致应用崩溃。调试日志显示:
W/le.music_playe(29628): Accessing hidden method Landroid/content/ContextWrapper;->getDisplay()Landroid/view/Display; (light greylist, linking) W/OnAudioQueryPlugin(29628): The application doesn't have access to the library E/AndroidRuntime(29628): FATAL EXCEPTION: main
初始及修改后的权限检查代码均未解决问题,核心原因是FutureBuilder的异步查询逻辑未等待权限流程完成就已触发。
解决方案
核心思路
通过状态变量标记权限状态,严格控制querySongs()的执行时机,确保仅在权限授予后才执行歌曲查询。
具体修改步骤
- 添加权限状态变量
在State类中新增布尔变量,用于追踪权限是否已授予:
class _HomeState extends State<Home> { final audioQuery = OnAudioQuery(); bool _hasPermission = false; // 新增权限状态标记 @override void initState() { super.initState(); checkPermission(); } // 后续方法 }
- 更新权限检查逻辑
修改checkPermission方法,在权限确认后更新状态变量:
Future<void> checkPermission() async { if (!kIsWeb) { bool permissionStatus = await audioQuery.permissionsStatus(); if (!permissionStatus) { // 请求权限后更新状态 permissionStatus = await audioQuery.permissionsRequest(); } setState(() { _hasPermission = permissionStatus; }); } else { // Web端无需存储权限,直接标记为已授权 setState(() { _hasPermission = true; }); } }
- 控制歌曲查询的执行时机
修改FutureBuilder,仅在_hasPermission为true时执行querySongs(),否则展示权限提示或加载状态:
FutureBuilder<List<SongModel>>( // 仅在权限通过后触发查询 future: _hasPermission ? audioQuery.querySongs( sortType: null, orderType: OrderType.ASC_OR_SMALLER, uriType: UriType.EXTERNAL, ignoreCase: true, ) : null, builder: (context, snapshot) { // 权限未通过时的UI if (!_hasPermission) { return const Center(child: Text("请授予存储权限以访问音乐")); } // 处理查询结果 switch (snapshot.connectionState) { case ConnectionState.waiting: return const Center(child: CircularProgressIndicator()); case ConnectionState.done: if (snapshot.hasError) { return Center(child: Text("加载失败: ${snapshot.error}")); } final songs = snapshot.data ?? []; return ListView.builder( itemCount: songs.length, itemBuilder: (context, index) { return ListTile(title: Text(songs[index].title)); }, ); default: return const SizedBox(); } }, )
补充说明
- 避免直接在
FutureBuilder的future参数中写入异步调用,否则组件每次重建都会重复执行查询逻辑; - 若用户拒绝权限,可在
checkPermission中添加引导逻辑,跳转到应用设置页面开启权限。
内容的提问来源于stack exchange,提问作者Esa
相关产品推荐
相关产品推荐

