当我们在settings中试听铃声,这时候突然来了一个电话,那么会出现试听铃声和来电铃声同时播放的情况。当然,此情况同样适用于闹钟铃声,媒体音乐播放等。那么怎么解决这个问题呢?这就需要当音频焦点。---》
因为系统中可能会有多个应用程序会播放音频,所以需要考虑他们之间该如何交互,为了避免多个应用程序同时播放音乐,Android 系统使用音频焦点来进行统一管理,即只有获得了音频焦点的应用程序才可以播放音乐。 您的应用程序在开始播放音频文件前,首先应该请求获得音频焦点,并且应该同时注册监听音频焦点的丢失通知,即如果音频焦点被系统或其他的应用程序抢占时,您的应用程序可以做出合适的响应。
首先,我要获取一个音频焦点并管理它。
private boolean requestFocus() { // Request audio focus for playback int result = mAudioManager.requestAudioFocus(afChangeListener, AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); return result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED; } OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() { public void onAudioFocusChange(int focusChange) { if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT || focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { // Pause playback if (mLocalPlayer !=null && mLocalPlayer.isPlaying()){ mLocalPlayer.pause(); } } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { // Resume playback startLocalPlayer(); } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { mAudioManager.abandonAudioFocus(afChangeListener); // Stop playback if (mLocalPlayer !=null && mLocalPlayer.isPlaying()){ mLocalPlayer.stop(); } } } };
可以很清晰的看见,上面的第一个方法是获取音频焦点,通过requestAudioFocus()来实现。而第二个方法就是对音频焦点进行监听并管理。在这里,要先知道以上几个值的含义:
- AUDIOFOCUS_GAIN_TRANSIENT:只是短暂获得,一会就释放焦点,比如你只是想发个notification时用下一秒不到的铃声。
- AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:只是背景获得,之前的音频焦点使用者无需释放焦点给我,我将与其共同使用。
- AUDIOFOCUS_GAIN:我要求完全获得焦点,其他人需要释放焦点。比如我要播放音乐了,这时就要抢占整个音频焦点。
- AUDIOFOCUS_LOSS:你会长时间的失去焦点,所以不要指望在短时间内能获得。请结束自己的相关音频工作并做好收尾工作。
- AUDIOFOCUS_LOSS_TRANSIENT:你会短暂的失去音频焦点,你可以暂停音乐,但不要释放资源,因为你一会就可以夺回焦点并继续使用。
知道了以上几个字段的含义,在对应的状态,我们就能做相应的处理。比如AUDIOFOCUS_LOSS_TRANSIENT短暂失去焦点,我们就暂停我们的音乐。AUDIOFOCUS_LOSS长期失去焦点,就直接停掉音乐。AUDIOFOCUS_GAIN我获取了焦点,那么我就要开始播放音乐了(由于我完全获取了焦点,其他音乐就无法播放了,自然当前就只有一个音乐进行播放)。
获取音频焦点,就要释放音频焦点:(在哪里释放,就看当时的代码吧)
private void destroyLocalPlayer() { if (mLocalPlayer != null) { mLocalPlayer.reset(); mLocalPlayer.release(); mLocalPlayer = null; synchronized (sActiveRingtones) { sActiveRingtones.remove(this); } } mAudioManager.abandonAudioFocus(afChangeListener); }
在解决这个问题的时候,我选择在每次播放试听铃声时,获取音频焦点(何时获取,也要看当时代码情况):
private void startLocalPlayer() { if (mLocalPlayer == null) { return; } synchronized (sActiveRingtones) { sActiveRingtones.add(this); } mLocalPlayer.setOnCompletionListener(mCompletionListener); if(requestFocus()){ mLocalPlayer.start(); } }
成功获取到焦点,才可以播放当前的试听铃声哦!
时间: 2024-10-12 21:06:07