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

使用ExoPlayer 2.18.1无法播放多个资产音频文件的技术问询

解决ExoPlayer 2.18.1资产音频无播放问题

以下是针对你遇到的无音频播放问题的排查点和修正方案:

1. 补充必要的ExoPlayer依赖

仅依赖exoplayer-core可能不足以支持完整的音频播放能力,需添加音频模块依赖:

api "com.google.android.exoplayer:exoplayer-core:2.18.1"
api "com.google.android.exoplayer:exoplayer-audio:2.18.1"

2. 修正资产URI与媒体源配置

确认资产文件路径正确性(文件名区分大小写、需放在assets根目录),可使用更明确的方式构建媒体项:

// 构建资产媒体项
val mediaItem = MediaItem.fromUri("asset:///$soundFile")
// 或使用更直观的AssetMediaItem
// val mediaItem = AssetMediaItem.Builder(soundFile).build()

val mediaSource = ProgressiveMediaSource.Factory(DefaultDataSource.Factory(this))
    .createMediaSource(mediaItem)

3. 处理音频焦点(核心修复点)

在Service中播放音频必须请求系统音频焦点,否则会被系统限制播放:

// 定义音频焦点请求
private val audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
    .setOnAudioFocusChangeListener { focusChange ->
        when(focusChange) {
            AudioManager.AUDIOFOCUS_LOSS -> exoPlayer?.pause()
            AudioManager.AUDIOFOCUS_GAIN -> exoPlayer?.play()
        }
    }
    .build()

private fun requestAudioFocus(): Boolean {
    val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
    return audioManager.requestAudioFocus(audioFocusRequest) == AudioManager.AUDIOFOCUS_REQUEST_GRANTED
}

4. 修正播放器初始化与播放逻辑

避免在prepare()后立即调用play(),应监听播放器准备完成事件,确保媒体加载完成后再启动播放:

private fun initializeExoPlayer(soundFile: String): ExoPlayer {
    val trackSelector = DefaultTrackSelector(this).apply {
        setParameters(buildUponParameters().setMaxVideoSizeSd())
    }
    val exoPlayer = ExoPlayer.Builder(this)
        .setTrackSelector(trackSelector)
        .build()

    // 构建媒体源
    val mediaItem = MediaItem.fromUri("asset:///$soundFile")
    val mediaSource = ProgressiveMediaSource.Factory(DefaultDataSource.Factory(this))
        .createMediaSource(mediaItem)

    exoPlayer.setMediaSource(mediaSource)
    exoPlayer.repeatMode = Player.REPEAT_MODE_ALL

    // 监听准备完成,获取焦点后播放
    exoPlayer.addListener(object : Player.Listener {
        override fun onPlaybackStateChanged(playbackState: Int) {
            super.onPlaybackStateChanged(playbackState)
            if (playbackState == Player.STATE_READY && requestAudioFocus()) {
                exoPlayer.play()
            }
        }
    })

    exoPlayer.prepare()
    return exoPlayer
}

5. 规范Service生命周期的播放器管理

在PlayerService的onDestroy()中释放资源,避免内存泄漏:

override fun onDestroy() {
    super.onDestroy()
    exoPlayer?.release()
    // 放弃音频焦点
    val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
    audioManager.abandonAudioFocusRequest(audioFocusRequest)
}

额外排查点

  • 确认assets目录下的音频文件存在,文件名无拼写错误
  • 检查设备媒体音量未静音、系统未限制应用音频权限
  • 查看Logcat中的ExoPlayer相关日志(搜索ExoPlayer关键词),定位加载或播放错误

内容的提问来源于stack exchange,提问作者Sidharth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 03:11:50