项目中,我遇到了一个这样的问题。后台正在播放Music,此时去Settings中的铃声与提示音中设置一个通知音铃声,在选择铃声时会播放此铃声,但是却并没有中断Music,两者会同时播放,听起来很混乱。那是因为,播放铃声的时候,没有去获取一个音频焦点,没有竞争通道。我们知道,听歌的时候,来了电话,这时歌曲肯定会被暂停,直到通话结束后才会继续播放。就是因为做出了这样的处理。
有一个专门管理音频的类,叫AudioManager 。位于 frameworks/base/media/java/android/media/AudioManager.java
通过getSystemService(Context.AUDIO_SERVICE)方法获得AudioManager实例对象。在必要的地方调用requestAudioFocus方法来获取音频焦点,此时就会暂停其他的音频。然后一定要在操作结束的地方,调用abandonAudioFocus释放掉音频焦点,才能恢复之前的播放。
import android.media.AudioManager;
AudioManager am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE)
申请的时候:
am.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
其中第一个参数是AudioManager.OnAudioFocusChangeListener,每当音频焦点有变动的时候其onAudioFocusChange()方法被调用。如果不需要监听,就是null 。第二个参数是streamType,指音频的类型,可取为STREAM_VOICE_CALL(通话)、STREAM_SYSTEM(系统声音)、STREAM_RING(铃声)、STREAM_MUSIC(音乐)、STREAM_ALARM(闹铃声),这里取的是音乐。第三个参数durationHint,是持续性的指示: AUDIOFOCUS_GAIN指示申请得到的Audio Focus不知道会持续多久,一般是长期占有;AUDIOFOCUS_GAIN_TRANSIENT指示要申请的AudioFocus是暂时性的,会很快用完释放的;AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK不但说要申请的AudioFocus是暂时性的,还指示当前正在使用AudioFocus的可以继续播放。
释放的时候:
am.abandonAudioFocus(null);
通过这个方法来归还音频。参数就是获取焦点时注册的监听,也就是requestAudioFocus时的第一个参数,如果没有监听,就是null .
我上面提到的这个问题,就是在播放铃声的那个列表,OnItemClickListener时获取焦点,在列表销毁的时候释放焦点,就可以了,并不需要对音频状态的改变进行监听。但是OnAudioFocusChangeListener在AudioManager中是一个十分重要的知识点,顺便也整理一下:
import android.media.AudioManager.OnAudioFocusChangeListener;
private OnAudioFocusChangeListener mAudioFocusChangeListener = new OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_LOSS:
synchronized (this) {}
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
synchronized (this) {}
break;
case AudioManager.AUDIOFOCUS_GAIN:
synchronized (this) {}
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
synchronized (this) {}
break;
default:
break;
}
}
};
AUDIOFOCUS_GAIN: 你已经得到了音频焦点。
AUDIOFOCUS_LOSS: 你已经失去了音频焦点很长时间了。你必须停止所有的音频播放。因为你应该不希望长时间等待焦点返回,这将是你尽可能清除你的资源的一个好地方。例如,你应该释放MediaPlayer。
AUDIOFOCUS_LOSS_TRANSIENT:你暂时失去了音频焦点,但很快会重新得到焦点。你必须停止所有的音频播放,但是你可以保持你的资源,因为你可能很快会重新获得焦点。
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: 你暂时失去了音频焦点,但你可以小声地继续播放音频(低音量)而不是完全扼杀音频。