You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现其他应用播放音频时停止ExoPlayer电台流播放?

嘿,这个需求其实在Android音频生态里是靠**音频焦点(Audio Focus)**来实现的,ExoPlayer本身已经封装了相关能力,不用你自己从零监听所有事件,下面一步步给你拆解:

核心方案:利用Android音频焦点机制

Android系统通过音频焦点来协调多个应用的音频播放——当一个应用要播放音频时,需要先向系统请求焦点;当其他应用请求焦点时,当前持有焦点的应用会收到通知,这时候咱们就可以暂停自己的电台流。

1. 最省心:用ExoPlayer自动处理音频焦点

ExoPlayer内置了音频焦点的管理逻辑,你只需要配置好播放器的音频属性,让它自动接管焦点处理就行:

// 配置你的电台流对应的音频属性
val audioAttributes = AudioAttributes.Builder()
    .setContentType(C.CONTENT_TYPE_MUSIC) // 电台流属于音乐类内容
    .setUsage(C.USAGE_MEDIA)
    .build()

// 给播放器设置音频属性,第二个参数设为true,让播放器自动处理焦点
player.setAudioAttributes(audioAttributes, true)

这样设置后,当其他应用(比如音乐APP、通话)抢占音频焦点时,ExoPlayer会自动暂停播放;当焦点重新回到你的应用时,还能自动恢复播放(这个逻辑可以通过播放器的参数微调)。

2. 自定义处理:手动监听焦点变化

如果默认的自动逻辑不够满足你的需求(比如想在暂停时显示提示、做额外的UI操作),可以手动设置焦点回调,精细控制每个场景的行为:

// 先创建音频焦点请求对象
val audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
    .setAudioAttributes(audioAttributes)
    .setOnAudioFocusChangeListener { focusChange ->
        when (focusChange) {
            AudioManager.AUDIOFOCUS_LOSS -> {
                // 永久失去焦点(比如用户打开了另一个音乐APP),直接停止播放
                player.stop()
            }
            AudioManager.AUDIOFOCUS_LOSS_TRANSIENT -> {
                // 暂时失去焦点(比如来电、微信语音通话),暂停播放
                player.pause()
            }
            AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK -> {
                // 暂时失去焦点,但可以降低音量继续播放(比如导航播报)
                player.volume = 0.3f
            }
            AudioManager.AUDIOFOCUS_GAIN -> {
                // 重新获得焦点,恢复播放和正常音量
                player.play()
                player.volume = 1.0f
            }
        }
    }
    .build()

// 手动向系统请求音频焦点
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
val result = audioManager.requestAudioFocus(audioFocusRequest)
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    player.play()
}

这种方式需要你自己管理焦点的请求和释放,适合有特殊业务逻辑的场景。

3. 可选补充:监听通话状态

其实音频焦点机制已经能覆盖来电/通话的场景,但如果你需要更直接地监听通话状态,可以注册TelephonyManager的监听:

val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
telephonyManager.listen(object : PhoneStateListener() {
    override fun onCallStateChanged(state: Int, phoneNumber: String?) {
        super.onCallStateChanged(state, phoneNumber)
        when (state) {
            // 来电响铃或正在通话时,暂停播放
            TelephonyManager.CALL_STATE_RINGING, TelephonyManager.CALL_STATE_OFFHOOK -> {
                if (player.isPlaying) player.pause()
            }
            // 通话结束后,恢复播放(根据你的需求调整)
            TelephonyManager.CALL_STATE_IDLE -> {
                player.play()
            }
        }
    }
}, PhoneStateListener.LISTEN_CALL_STATE)

注意:Android 10及以上需要申请READ_PHONE_STATE权限,而且这个属于额外补充,一般情况下用音频焦点就足够了。

总结
  • 优先用ExoPlayer自带的自动音频焦点处理,代码少、逻辑稳,能自动响应所有其他音频播放/来电场景;
  • 有特殊需求时,再手动实现焦点回调来定制行为;
  • 通话监听是可选操作,非必须。

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

火山引擎 最新活动