You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 09:43:04