androidx.media2.player.MediaPlayer双实例同播设置AudioAttributes无响应问题
问题根本原因
- 播放器准备状态未对齐:你当前仅监听了音频播放器的prepare完成回调就直接触发两个播放器的播放操作,此时视频播放器的prepare异步操作大概率还未执行完成。未进入prepared状态的MediaPlayer调用play()会触发内部状态错误,轻则无音频输出、重则抢占系统音视频渲染资源导致两个播放器都无法正常工作。你用到的
Thread.sleep(5000)刚好为视频播放器留出了足够的后台准备时间,因此能临时绕过问题,但不同设备、不同媒体文件的prepare耗时差异极大,该方案完全不可靠。 - 主线程阻塞的错误副作用:你给prepare回调指定了主线程Executor,
Thread.sleep(5000)会直接阻塞主线程5秒,虽然刚好等来了视频播放器的准备完成,但会带来界面卡顿、ANR的高风险,属于不符合Android开发规范的错误写法。 - 音频焦点竞争冲突:两个独立的MediaPlayer实例默认会各自申请音频焦点,相同USAGE属性的音频请求会触发系统的音频焦点抢占逻辑,最终可能导致两个播放器都无法拿到音频焦点,出现无声音输出的问题。你之前设置相同会话ID没有生效,是因为media2的音频焦点逻辑默认按播放器实例独立管理,仅会话ID一致不会自动合并焦点申请。
优化解决方案
1. 对齐两个播放器的准备状态
分别监听两个播放器的prepare完成事件,只有两个都完成准备后再同步触发播放,推荐用playWhenReady属性实现更精准的同步启动:
// 统计已完成prepare的播放器数量 var preparedCount = 0 val onPlayerPrepared = Runnable { preparedCount++ // 两个播放器都准备完成后,同步启动播放 if (preparedCount == 2) { audioPlayer.playWhenReady = true videoPlayer.playWhenReady = true } } // 初始化阶段先设置两个播放器为不自动播放 audioPlayer.playWhenReady = false videoPlayer.playWhenReady = false // 分别绑定准备完成监听 audioPlayer.prepare().addListener(onPlayerPrepared, ContextCompat.getMainExecutor(context)) videoPlayer.prepare().addListener(onPlayerPrepared, ContextCompat.getMainExecutor(context))
2. 统一管理音频焦点,避免竞争
禁用两个播放器的自动音频焦点处理逻辑,全局申请一次音频焦点,拿到焦点后再启动播放,从根源避免焦点冲突:
// 构造全局音频焦点申请请求 val audioAttrs = AudioAttributesCompat.Builder() .setContentType(AudioAttributesCompat.CONTENT_TYPE_MOVIE) .setUsage(AudioAttributesCompat.USAGE_MEDIA) .build() val focusRequest = AudioFocusRequestCompat.Builder(AudioManager.AUDIOFOCUS_GAIN) .setAudioAttributes(audioAttrs) .build() val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager val focusResult = audioManager.requestAudioFocus(focusRequest) if (focusResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { // 焦点申请成功后,禁用两个播放器的自动焦点处理 audioPlayer.setHandleAudioFocus(false) videoPlayer.setHandleAudioFocus(false) // 后续执行设置MediaItem、prepare等逻辑 } // 页面销毁/播放结束时记得释放音频焦点 // audioManager.abandonAudioFocusRequest(focusRequest)
3. 播放过程动态校准进度
为了避免播放过程中出现音视频偏移,可每隔100ms比对两个播放器的当前进度,差值超过50ms时校准慢的一方的进度,保证同步效果。
内容的提问来源于stack exchange,提问作者Wiktor Nizio
相关产品推荐
相关产品推荐

