Flutter 3.24.4版本下在Android端加载Flutter资源音频文件的正确方法
Flutter 3.24.4版本下在Android端加载Flutter资源音频文件的正确方法
我之前在Flutter 3.x版本里也碰到过一模一样的问题,旧的基于PluginRegistry的方法确实已经被废弃,而且FlutterEngine里的AssetManager确实没有直接暴露的公共接口,不过你尝试的FlutterInjector方向是完全正确的,下面给你详细说下正确的实现步骤:
首先要确认:你当前的pubspec.yml配置是没问题的,audio/file.wav已经正确声明为Flutter资源,打包后会被放在Android APK的assets/flutter_assets子目录下,这是关键的路径前提。
1. 获取Flutter的AssetManager实例
在MainActivity.kt里,你可以通过FlutterInjector安全获取到Flutter使用的AssetManager,不需要依赖私有API:
import io.flutter.embedding.engine.FlutterInjector import android.content.res.AssetManager import android.media.MediaPlayer import java.io.* class MainActivity : FlutterActivity() { override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) // 获取Flutter的AssetManager实例 val flutterAssetManager = FlutterInjector.instance().flutterLoader().flutterAssetManager // 加载并处理音频文件 loadFlutterAudioAsset(flutterAssetManager) } private fun loadFlutterAudioAsset(assetManager: AssetManager) { // Flutter资源在Android AssetManager中的实际路径(必须加上flutter_assets前缀) val flutterAssetPath = "flutter_assets/audio/file.wav" // 分两种场景处理,根据你的音频播放需求选择 // 场景一:直接用AssetFileDescriptor处理(适合MediaPlayer等主流音频库) try { val assetFd = assetManager.openFd(flutterAssetPath) val mediaPlayer = MediaPlayer().apply { setDataSource(assetFd.fileDescriptor, assetFd.startOffset, assetFd.length) prepare() // 可在此调用start()播放,或保存实例后续使用 } } catch (e: IOException) { e.printStackTrace() // 处理文件不存在、读取失败等异常 } // 场景二:如果音频库必须要文件路径(不支持流/FileDescriptor),则复制到内部存储临时文件 val tempAudioFile = copyAssetToTempFile(assetManager, flutterAssetPath) tempAudioFile?.let { tempFile -> // 用临时文件路径初始化音频播放 // 例如:mediaPlayer.setDataSource(tempFile.absolutePath) } } // 将Asset文件复制到应用内部存储的临时文件 private fun copyAssetToTempFile(assetManager: AssetManager, assetPath: String): File? { return try { // 创建唯一的临时文件,存在应用内部存储目录 val tempFile = File(filesDir, "temp_audio_${System.currentTimeMillis()}.wav") assetManager.open(assetPath).use { inputStream -> FileOutputStream(tempFile).use { outputStream -> inputStream.copyTo(outputStream) } } tempFile } catch (e: IOException) { e.printStackTrace() null } } }
关键说明:
- 路径前缀问题:Flutter打包资源时,会把所有在
pubspec.yml中声明的资源放到Android的flutter_assets子目录下,所以实际访问路径必须加上flutter_assets/前缀,否则会找不到文件。 - API安全性:
FlutterInjector是Flutter官方提供的注入器,用来安全访问内部组件,比直接反射私有API更稳定,完全符合官方的设计意图。 - 场景选择:如果你的音频播放库支持
AssetFileDescriptor或输入流,优先选择场景一,避免额外的文件复制开销;如果必须要文件路径,再使用场景二的临时文件方案。
备注:内容来源于stack exchange,提问作者Levin Leesemann
相关产品推荐
相关产品推荐

