在给定的时间尽管只有一个活动可以运行,但Android是一个多任务环境。这对应用程序使用音频造成了一个特别大的难度,由于只有一个音频输出,可能会有好几个媒体服务争夺使用它。

Android 2.2之前,没有内置机制来解决这个问题,这可能在某些情况下导致糟糕的用户体验。例如,一个用户正在听音乐,同时另一个应用程序有很重要的事需要通知用户,由于吵闹的音乐用户可能不会听到提示音。从Android 2.2开始,Android平台为应用程序提供了一个方式来协商设备的音频输出,这个机制被称为音频焦点。

音频焦点是自然的合作,应用程序都期望(强烈鼓励)遵守音频焦点指南,但规则并不是系统强制执行的。如果应用程序失去音频焦点后想要播放嘈杂的音乐,在系统中没有什么会阻止他。然而,这样可能会让用户有更糟糕的体验,并可能卸载这运行不当的应用程序。

请求音频焦点,您必须从AudioManager调用requestAudioFocus()方法,

下面展示一个例子:

AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
 int result = audioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC,
 AudioManager.AUDIOFOCUS_GAIN);

 if (result != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
 // could not get audio focus.}er,每当音频焦点有变动的时候其onAudioFocusChange()方法被调用。
 您还应该在你的服务和活动上实现这个接口。 代码如下:
 class MyService extends Service
 implements AudioManager.OnAudioFocusChangeListener {
 // ....
 public void onAudioFocusChange(int focusChange) {
 // Do something based on focus change...
 }
 } AUDIOFOCUS_GAIN: 你已经得到了音频焦点。
 AUDIOFOCUS_LOSS: 你已经失去了音频焦点很长时间了。你必须停止所有的音频播放。因为你应该不希望长时间等待焦点返回,这将是你尽可能清除你的资源的一个好地方。例如,你应该释放MediaPlayer。
 AUDIOFOCUS_LOSS_TRANSIENT:你暂时失去了音频焦点,但很快会重新得到焦点。你必须停止所有的音频播放,但是你可以保持你的资源,因为你可能很快会重新获得焦点。
 AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: 你暂时失去了音频焦点,但你可以小声地继续播放音频(低音量)而不是完全扼杀音频。 下面是一个示例实现:
 public void onAudioFocusChange(int focusChange) {
 switch (focusChange) {
 case AudioManager.AUDIOFOCUS_GAIN:
 // resume playback
 if (mMediaPlayer == null) initMediaPlayer();
 else if (!mMediaPlayer.isPlaying()) mMediaPlayer.start();
 mMediaPlayer.setVolume(1.0f, 1.0f);
 break;
 case AudioManager.AUDIOFOCUS_LOSS:
 // Lost focus for an unbounded amount of time: stop playback and release media player
 if (mMediaPlayer.isPlaying()) mMediaPlayer.stop();
 mMediaPlayer.release();
 mMediaPlayer = null;
 break;
 case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
 // Lost focus for a short time, but we have to stop
 // playback. We don't release the media player because playback
 // is likely to resume
 if (mMediaPlayer.isPlaying()) mMediaPlayer.pause();
 break;
 case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
 // Lost focus for a short time, but it's ok to keep playing
 // at an attenuated level
 if (mMediaPlayer.isPlaying()) mMediaPlayer.setVolume(0.1f, 0.1f);
 break;
 }
 } 通过反射调用音频焦点方法或通过在一个单独类中实现所有的音频焦点特性,您可以实现向后兼容性(AudioFocusHelper 中阐明)。下面是这样一个类的示例:
er {
 AudioManager mAudioManager;
 // other fields here, you'll probably hold a reference to an interface
 // that you can use to communicate the focus changes to your Service

 public AudioFocusHelper(Context ctx, ) {
 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
 // ...
 }

 public boolean requestFocus() {
 return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
 mAudioManager.requestAudioFocus(mContext, AudioManager.STREAM_MUSIC,
 AudioManager.AUDIOFOCUS_GAIN);
 }

 public boolean abandonFocus() {
 return AudioManager.AUDIOFOCUS_REQUEST_GRANTED ==
 mAudioManager.abandonAudioFocus(this);
 }

 @Override
 public void onAudioFocusChange(int focusChange) {
 // let your service know about the focus change 
 }
 } 当你发现系统运行时API级别在8级或以上时,您可以创建AudioFocusHelper 类的一个实例,例如:
 Java代码
 if (android.os.Build.VERSION.SDK_INT >= 8) {
 mAudioFocusHelper = new AudioFocusHelper(getApplicationContext(), this);
 } else {
 mAudioFocusHelper = null;
 }

参考:http://mobile.51cto.com/android-309321.htm

http://blog.sina.com.cn/s/blog_645b74b90101e74f.html