使用音频焦点处理第三方播放器暂停与恢复
2016-05-11 本文已影响3599人
前世小书童
<p>
最近刚好有碰到第三方播放与我自己播放的冲突问题,因为其实对Android的音频开发并不是很了解,再经过各种Google后是成功的解决了这个问题,便顺便记录下来。
1.处理第三方播放器暂停与恢复首先得知道第三方播放器用的是什么播放的?
Android SDK 提供了3套音频播放的API,分别是:MediaPlayer,SoundPool,AudioTrack,
- MediaPlayer 更加适合在后台长时间播放本地音乐文件或者在线的流式资源;
- SoundPool 则适合播放比较短的音频片段,比如游戏声音、按键声、铃声片段等等,它可以同时播放多个音频;
- AudioTrack 则更接近底层,提供了非常强大的控制能力,支持低延迟播放,适合流媒体和VoIP语音电话等场景。
所以很自然的MediaPlayer是更加适合于第三方的播放器的,但是如果某些播放器用的并不是MediaPlayer那我也没有办法了,不在考虑的范围内
2.怎么暂停与恢复第三方播放器
其实标题就已经说明了,AudioFocus这个其实是音频焦点,一般情况下音乐播放器都会处理这个音频焦点的,在其丢失音频焦点的情况会将音频暂停或者停止的逻辑的,等到再次获取到音频焦点的情况下会再次恢复播放的。
怎么让第三方播放器失去音频焦点呢?自然是让我们的MediaPlayer获取到焦点就好了
-
音频焦点可以通过requestAudioFocus()方法获得,在音频焦点成功获取后,该方法会返回AUDIOFOCUS_REQUEST_GRANTED常量,否则,会返回AUDIOFOCUS_REQUEST_FAILED常量。
-
而让我们的MediaPlayer失去焦点abandonAudioFocus()方法,这会通知系统您的App不再需要音频焦点,并移除相关OnAudioFocusChangeListener的注册。如果释放的是短暂音调焦点,那么被打断的音频会被继续播放。
基本把原理都说明了,接下来贴下来我简单封装的MediaPlayerUtil类
public class MediaPlayerUtil {
private Context mContext;
private MediaPlayer mediaPlayer;
private AudioManager am;
private int mId;
public MediaPlayerUtil(Context context) {
this.mContext = context;
am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
}
public void startMediaPlayer(int id){
mId = id;
if (mediaPlayer != null) {
mediaPlayer.start();
} else {
initBeepSound(id);
mediaPlayer.start();
}
// Request audio focus for playback
int result = am.requestAudioFocus(afChangeListener,
// Use the music stream.
AudioManager.STREAM_MUSIC, // Request permanent focus.
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
mediaPlayer.start();
// Start playback. // ¿ªÊ¼²¥·ÅÒôÀÖÎļþ
}
}
public void stopMediaPlayer(){
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}else if (mediaPlayer != null){
mediaPlayer = null;
}
am.abandonAudioFocus(afChangeListener);
}
private void initBeepSound(int id) {
if (mediaPlayer == null) {
// The volume on STREAM_SYSTEM is not adjustable, and users found it
// too loud,
// so we now play on the music stream.
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnCompletionListener(beepListener);
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
stopMediaPlayer();
}
});
AssetFileDescriptor file = mContext.getResources().openRawResourceFd(
id);
try {
mediaPlayer.setDataSource(file.getFileDescriptor(),
file.getStartOffset(), file.getLength());
file.close();
mediaPlayer.prepare();
} catch (IOException e) {
mediaPlayer = null;
}
}
}
AudioManager.OnAudioFocusChangeListener afChangeListener = new AudioManager.OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
if (mediaPlayer == null) {
initBeepSound(mId);
} else if (!mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
// Resume playback
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
am.abandonAudioFocus(afChangeListener);
// Stop playback
} else if (focusChange == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
} else if (focusChange == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
}
}
};
private final MediaPlayer.OnCompletionListener beepListener = new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.seekTo(0);
}
};
}
简单的使用还是没有问题的,因为我使用的场景也只是播放一小段音频,所以大家只需要参考使用音频焦点的部分就好了