视频讲解:http://www.eyeandroid.com/thread-15896-1-1.htmlhtml
因为不少应用程序均可以播放音频,所以在播放前考虑它们如何交互就显得很重要了,为了不同时出现多个声音,Android使用音频焦点(AudioFocus)来控制音频的播放 - 仅仅是获取到Audio Focus的应用程序才可以播放音频。android
在应用程序开始播放音频以前,它须要通过发出请求[request]à接受请求[receive] à音频焦点锁定[AudioFocus]的过程。一样它须要知道如何监听音频焦点的丢失并进行合适的响应。函数
请求获取音频焦点spa
在开始播放音频以前,应用程序必须先获取须要处理的音频流的音频焦点。音频焦点能够经过requestAudioFocus()方法得到,在音频焦点成功获取后,该方法会返回AUDIOFOCUS_REQUEST_GRANTED常量,不然会返回AUDIOFOCUS_REQUEST_FAILED常量。orm
咱们必须指定正在使用的是哪一个音频流,并且是否想请求短暂仍是永久的Audio Focus。短暂的焦点锁定:当期待播放一个短暂的音频的时候(好比播放导航指示);永久的焦点锁定:当计划播放可预期到的较长的音频的时候(好比播放音乐)。视频
下面是一个在播放音乐的时候请求永久音频焦点的例子,咱们必须在开始播放以前当即请求音频焦点,好比在用户点击播放或者游戏程序中下一关开始的片头音乐。htm
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);游戏 ...事件 // Request audio focus for playbackci int result = am.requestAudioFocus(afChangeListener,// Use the music stream. AudioManager.STREAM_MUSIC,// Request permanent focus. AudioManager.AUDIOFOCUS_GAIN); if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { am.registerMediaButtonEventReceiver(RemoteControlReceiver); // Start playback. } |
一旦结束了播放,须要确保调用abandonAudioFocus()方法。这样会通知系统说你再也不须要获取焦点而且取消注册AudioManager.OnAudioFocusChangeListener的监听。若是是释放短暂音频焦点的状况下,可让以前被打断的应用程序继续播放。
// Abandon audio focus when playback complete am.abandonAudioFocus(afChangeListener); |
当请求短暂音频焦点的时候,咱们能够选择是否开启“ducking”。Ducking是一个特殊的机制使得容许音频间歇性的短暂播放。
一般状况下,一个好的应用程序在失去音频焦点的时候它会当即保持安静。若是咱们选择在请求短暂音频焦点的时候开启了ducking,那意味着其它应用程序能够继续播放,仅仅是在这一刻下降本身的音量,在从新获取到音频焦点后恢复正常音量(也就是说:不用理会这个短暂焦点的请求,这并不会致使目前在播放的音频受到牵制,好比在播放音乐的时候忽然出现一个短暂的短信提示声音,这个时候仅仅是把播放歌曲的音量暂时调低,好让短信声可以让用户听到,以后立马恢复正常播放)。
// Request audio focus for playback int result = am.requestAudioFocus(afChangeListener,// Use the music stream. AudioManager.STREAM_MUSIC,// Request permanent focus. AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK); if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { // Start playback. } |
Ducking很是适合间歇性播放音频的应用程序,例如播放导航仪的提示。
当其余应用程序经过上述方式请求音频焦点时,您所注册的监听器能够判断是否获丢失了长期或短暂(能够选择是否支持Ducing)的音频焦点。
处理失去音频焦点
应用程序请求并获得音频焦点后,当其余应用程序请求焦点时,先前的应用程序就会失去焦点。您的应用程序须要根据失去音频焦点的类型来进行相应的处理。
请求音频焦点时注册的音频焦点监听器中有onAudioFocusChange(int)回调函数,该回调函数会接收描述焦点变化事件的参数。须要注意的是,失去音频焦点的事件类型与请求焦点的类型相对应——失去长期焦点(AUDIOFOCUS_LOSS)、短暂焦点(AUDIOFOCUS_LOSS_TRANSIENT)和Ducking方式的短暂焦点(AUDIOFOCUS_LOSS_TRANSIENT)。
失去短暂焦点:通常状况下,应用程序在失去短暂音频焦点时,应该中止播放并记录下播放状态。并且须要继续监听音频焦点的变化,当从新得到音频焦点时,须要在从先前暂停的地方继续播放。
失去永久焦点:假设另一个程序开始播放音乐等,那么咱们的程序就应该有效的结束本身。实用的作法是中止播放,移除Media Button监听广播,容许新的音频播放器独占监听那些按钮事件,而且放弃本身的音频焦点。
在下面的代码中,当应用程序失去短暂的音频焦点时会暂停播放,当从新得到焦点时会继续播放。当失去的是长期音频焦点时,就会取消媒体按键事件接收器的注册并中止对音频焦点变化的监听。
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() { public void onAudioFocusChange(int focusChange) { if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT // Pause playback } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { // Resume playback } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { am.unregisterMediaButtonEventReceiver(RemoteControlReceiver); am.abandonAudioFocus(afChangeListener); // Stop playback } } }; |
在上面失去短暂焦点的例子中,若是容许ducking,那么咱们能够选择“duck”的行为而不是暂停当前的播放。
闪避
Ducking是一个特殊的机制使得容许音频间歇性地短暂播放。在Ducking的状况下,正常播放的歌曲会下降音量来凸显这个短暂的音频声音,这样既让这个短暂的声音比较突出,又不至于打断正常的声音。
下面的代码会使应用程序在暂时失去焦点时下降媒体播放器的音量,并在从新得到音频焦点时恢复到原来的音量大小。
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() { public void onAudioFocusChange(int focusChange) { if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { // Lower the volume } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { // Raise it back to normal } } }; |
监听失去音频焦点是最重要的广播之一,但不是惟一须要监听的广播。系统广播了一系列的intent来警示你去改变用户的音频使用体验。下节课会演示如何监视那些广播来提高用户的总体体验。