Flutter中使用audioplayer播放音频遇Unable to load asset错误求助
问题:Flutter点击按钮播放音频提示“Unable to load asset”错误
我想要实现用户点击按钮时播放音频的功能,尝试了多种方法但始终提示“Unable to load asset”错误。我之前处理过资源文件,推测这是新问题,恳请各位帮忙解决。
代码实现
// ignore_for_file: prefer_const_constructors, file_names, non_constant_identifier_names import 'dart:async'; import 'package:dyslexia/pages/data/DataSoundLevel1/DataQ1SoundL1.dart'; import 'package:dyslexia/pages/level1/round_2/Q8sound.dart'; import 'package:flutter/material.dart'; import 'package:flutter_tabler_icons/flutter_tabler_icons.dart'; import 'package:audioplayers/audioplayers.dart'; import '../../../utilities/QuestionWidget.dart'; class Q7sound extends StatefulWidget { const Q7sound({Key? key}) : super(key: key); @override State<Q7sound> createState() => _Q7soundState(); } class _Q7soundState extends State<Q7sound> { String question = "Listen to this letter sound and then choose the letter whose sound you hear"; var changeButton = false; bool changecolourC = false; bool changecolourW1 = false; bool changecolourW2 = false; bool changecolourW3 = false; double elev = 10; bool changeColor = false; String letter = "p"; bool buttonPressed1 = false; bool isPlayingMsg = false; var istap = false; int clicksPerpage = 0; int correctAns = 0; int incorrectAns = 0; int timeFirstClick = 0; num duration = 0; List timeIntervalClicks = []; int timer = 0; bool canceltimer = false; void starttimer() async { const onesec = Duration(seconds: 1); Timer.periodic(onesec, (Timer t) { if (mounted) { setState(() { timer = timer + 1; }); } }); } AudioPlayer player = AudioPlayer(); num countDuration() { for (int i = 0; i < timeIntervalClicks.length; i++) { duration = duration + timeIntervalClicks[i]; } return duration; } DataQ1soundL1 data = new DataQ1soundL1(); void mappData() { data.clicksPerpage = clicksPerpage; data.correctAns = correctAns; data.incorrectAns = incorrectAns; data.timeFirstClick = timeFirstClick; data.timeIntervalClicks = timeIntervalClicks; data.duration = countDuration(); } @override Widget build(BuildContext context) { bool isPlayingMsg = false; return Scaffold( appBar: AppBar( automaticallyImplyLeading: true, backgroundColor: Colors.cyan, title: Text("AD&DY"), ), body: Padding( padding: const EdgeInsets.all(14.0), child: Column(children: [ Row(mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( changecolourC ? TablerIcons.circle_check : changecolourW1 ? TablerIcons.circle_check : changecolourW2 ? TablerIcons.circle_check : changecolourW3 ? TablerIcons.circle_check : TablerIcons.circle_dashed, size: 30, color: changecolourC ? Colors.green : changecolourW1 ? Colors.red : changecolourW2 ? Colors.red : changecolourW3 ? Colors.red : Colors.black, ), Icon( TablerIcons.line_dashed, size: 30, ), Icon( TablerIcons.circle_dashed, size: 30, ), Icon( TablerIcons.line_dashed, size: 30, ), Icon( TablerIcons.circle_dashed, size: 30, ), Icon( TablerIcons.line_dashed, size: 30, ), Icon( TablerIcons.circle_dashed, size: 30, ), Icon( TablerIcons.line_dashed, size: 30, ), Icon( TablerIcons.circle_dashed, size: 30, ), ]), SizedBox(height: MediaQuery.of(context).size.height * 0.05), QuestionWidget(question: question), SizedBox(height: MediaQuery.of(context).size.height * 0.1), //audio button Material( elevation: 5, color: Colors.cyan[50], child: ListTile( onTap: () async { player.play(AssetSource("/sound/p.mp3")); isPlayingMsg = true; clicksPerpage += 1; timeFirstClick = timer.toInt(); timeIntervalClicks.add(timer.toInt()); if (mounted) { setState(() { timer = 0; }); } }, leading: Icon(isPlayingMsg ? Icons.stop : Icons.play_arrow), title: Text(isPlayingMsg ? "Stop" : "Play", textScaleFactor: 1.2, style: TextStyle( color: Colors.black, )), ), ), Divider( thickness: 1.0, ), SizedBox(height: MediaQuery.of(context).size.height * 0.1), Wrap( spacing: 10, runSpacing: 5, children: [ Material( elevation: elev, shadowColor: Colors.grey, color: changecolourW1 ? Colors.red : Colors.cyan, borderRadius: BorderRadius.circular(changeButton ? 50 : 8), child: InkWell( onTap: () { clicksPerpage += 1; incorrectAns += 1; timeIntervalClicks.add(timer.toInt()); if (mounted) { setState(() { changecolourW1 = true; elev = 0; timer = 0; }); } }, child: Container( height: 50, width: 50, alignment: Alignment.center, child: Text("M", textScaleFactor: 1.2, style: TextStyle( color: Colors.black, ))), ), ), Material( elevation: elev, shadowColor: Colors.grey, color: changecolourC ? Colors.green : Colors.cyan, borderRadius: BorderRadius.circular(changeButton ? 50 : 8), child: InkWell( onTap: () { clicksPerpage += 1; correctAns += 1; timeIntervalClicks.add(timer.toInt()); if (mounted) { setState(() { changecolourC = true; elev = 0; timer = 0; }); } istap = true; }, child: Container( height: 50, width: 50, alignment: Alignment.center, child: Text("P", textScaleFactor: 1.2, style: TextStyle( color: Colors.black, ))), ), ), Material( elevation: elev, shadowColor: Colors.grey, color: changecolourW2 ? Colors.red : Colors.cyan, borderRadius: BorderRadius.circular(changeButton ? 50 : 8), child: InkWell( onTap: () { clicksPerpage += 1; incorrectAns += 1; timeIntervalClicks.add(timer.toInt()); if (mounted) { setState(() { changecolourW2 = true; elev = 0; timer = 0; }); } }, child: Container( height: 50, width: 50, alignment: Alignment.center, child: Text("R", textScaleFactor: 1.2, style: TextStyle( color: Colors.black, ))), ), ), Material( elevation: elev, shadowColor: Colors.grey, color: changecolourW3 ? Colors.red : Colors.cyan, borderRadius: BorderRadius.circular(changeButton ? 50 : 8), child: InkWell( onTap: () { clicksPerpage += 1; incorrectAns += 1; timeIntervalClicks.add(timer.toInt()); if (mounted) { setState(() { changecolourW3 = true; elev = 0; timer = 0; }); } }, child: Container( height: 50, width: 50, alignment: Alignment.center, child: Text("S", textScaleFactor: 1.2, style: TextStyle( color: Colors.black, ))), ), ), ], ), SizedBox(height: MediaQuery.of(context).size.height * 0.1), Material( color: Colors.black, borderRadius: BorderRadius.circular(changeButton ? 50 : 8), child: InkWell( onTap: () { mappData(); Duration(seconds: 4); Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (context) => Q8sound())); }, child: AnimatedContainer( duration: Duration(seconds: 4), width: changeButton ? 50 : 150, height: 50, alignment: Alignment.center, child: changeButton ? Icon( Icons.done, color: Colors.black, ) : Text( 'Next', style: TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 18), ), ), ), ), ]), ), ); } }
错误信息
E/flutter (14336): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Unable to load asset: assets/sound/p.mp3 E/flutter (14336): #0 PlatformAssetBundle.load package:flutter/…/services/asset_bundle.dart:258 E/flutter (14336): <asynchronous suspension> E/flutter (14336): #1 AudioCache.fetchToMemory package:audioplayers/src/audio_cache.dart:75 E/flutter (14336): <asynchronous suspension> E/flutter (14336): #2 AudioCache.load package:audioplayers/src/audio_cache.dart:101 E/flutter (14336): <asynchronous suspension> E/flutter (14336): #3 _AudioPlayerLocalAssetState.playMusic package:dyslexia/…/round_2/playeraudio.dart:67 E/flutter (14336): <asynchronous suspension> E/flutter (14336):
解决方案
针对这个错误,从代码和资源配置角度排查几个关键点:
修正资源路径格式
代码里写的是player.play(AssetSource("/sound/p.mp3")),AssetSource的路径不需要开头的斜杠,改成AssetSource("sound/p.mp3")。因为Flutter的资源路径是相对于pubspec.yaml里配置的assets目录,开头加斜杠会导致路径错误。检查pubspec.yaml的资源配置
确保你已经在pubspec.yaml里正确声明了音频资源:flutter: assets: - sound/p.mp3 # 如果sound目录下有多个文件,可以直接声明整个目录: # - sound/配置完后执行
flutter pub get,并重启IDE或热重载应用,确保资源被正确加载。确认文件路径和大小写
Flutter的资源路径区分大小写,检查音频文件实际路径是sound/p.mp3还是Sound/P.mp3,要和代码里的路径完全一致。同时确认文件确实存在于项目对应目录下,没有拼写错误。清理缓存并重启应用
执行flutter clean清理项目缓存,然后重新运行应用,避免缓存导致的资源加载异常。
内容的提问来源于stack exchange,提问作者Daniyal Haider
相关产品推荐
相关产品推荐

