使用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
相关产品推荐
相关产品推荐

