1.动态更新SeekBar
以前的思路是MediaPlayer 隔几百ms notify注册了监听的activity,今天发现有更为简单的方式
定义变量
SeekBar mProgressBar = null;//刷新对象
Handler mProgressRefresher;//通过handler刷新界面
private static final int DELAY_MILLIS = 200;//刷新间隔
MediaPlayer mPlayer = null;
OnCreate 变量初始化
mProgressBar = (SeekBar) findViewById(R.id.audio_progress);
mProgressRefresher = new Handler();
mPlayer = new MediaPlayer();
mPlayer.setOnPreparedListener(this);
mPlayer.setOnCompletionListener(this);
当开始播放歌曲时(一般是调用play方法时)开始更新界面
mProgressRefresher.removeCallbacksAndMessages(null);
mProgressBar.setMax(mPlayer.getDuration());
mProgressRefresher.postDelayed(new ProgressRefresher(), DELAY_MILLIS);
try {
mPlayer.setDataSource(this, uri);
mPlayer.prepareAsync();
} catch (IOException e) {
Log.d(TAG, "Failed to open file: " + e);
finish();
}
核心:递归调用handler 更新界面
private class ProgressRefresher implements Runnable {
@Override
public void run() {
if (mPlayer != null) {
int position = mPlayer.getCurrentPosition();
mProgressBar.setProgress(position);
}
mProgressRefresher.removeCallbacksAndMessages(null);
mProgressRefresher.postDelayed(new ProgressRefresher(), DELAY_MILLIS);//此处为核心
}
}
2.OnAudioFocusChangeListener 的使用
OnAudioFocusChangeListener简介
OnAudioFocusChangeListener简单来说是当android系统同时有两个应用需要使用AudioManager时,为了处理两个应用的声音播放优先级而存在的.如果不使用OnAudioFocusChangeListener,会导致android 音频系统的混乱,比如会同时有两个应用在播放歌曲,歌曲播放中,有电话过来,通话结束音乐不再播放等等现象.
在其他博客中,这种机制称为AudioFocus竞争机制.当焦点变化时,OnAudioFocusChangeListener会收到AudioManager发出的以下通知
AUDIOFOCUS_GAIN:获得了Audio Focus;
AUDIOFOCUS_LOSS:失去了Audio Focus,并将会持续很长的时间。这里因为可能会停掉很长时间,所以不仅仅要停止Audio的播放,最好直接释放掉Media资源。而因为停止播放Audio的时间会很长,如果程序因为这个原因而失去AudioFocus,最好不要让它再次自动获得AudioFocus而继续播放,不然突然冒出来的声音会让用户感觉莫名其妙,感受很不好。这里直接放弃AudioFocus,当然也不用再侦听远程播放控制【如下面代码的处理】。要再次播放,除非用户再在界面上点击开始播放,才重新初始化Media,进行播放。
AUDIOFOCUS_LOSS_TRANSIENT:暂时失去Audio Focus,并会很快再次获得。必须停止Audio的播放,但是因为可能会很快再次获得AudioFocus,这里可以不释放Media资源;
AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:暂时失去AudioFocus,但是可以继续播放,不过要在降低音量。
具体使用
/**
* 焦点变化
*/
OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int focusChange) {
Log.d(TAG, "mPlayer: [" + mPlayer + "] ,focusChange: ["
+ focusChange + "]");
Log.i(TAG, "onAudioFocusChange");
if (mPlayer == null) {
mAudioManager.abandonAudioFocus(this);
return;
}
switch (focusChange) {
//丢失焦点
case AudioManager.AUDIOFOCUS_LOSS:
mPlayer.pause();
break;
//Used to indicate a transient loss of audio focus.
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
/**
* Used to indicate a transient loss of audio focus where the loser of the audio focus can
* lower its output volume if it wants to continue playing (also referred to as "ducking"), as
* the new focus owner doesn't require others to be silent.
*/
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
if (mPlayer.isPlaying()) {
mPlayer.pause();
}
break;
//Used to indicate a gain of audio focus, or a request of audio focus, of unknown duration.
//应理解为重新获取焦点
case AudioManager.AUDIOFOCUS_GAIN:
if (mPlayer != null) {
mPlayer.start();
return;
}
break;
}
}
};
音乐播放器应该做到使用前申请AudioFocus,使用完毕后释放AudioFocus
使用前申请Focus:(基本在play方法中)
if (AudioManager.AUDIOFOCUS_REQUEST_FAILED == mAudioManager
.requestAudioFocus(mAudioFocusListener,
AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)) {
Log.d(TAG, "start() AUDIOFOCUS_REQUEST_FAILED: "
+ AudioManager.AUDIOFOCUS_REQUEST_FAILED);
return;
}
使用完毕后释放Focus:(基本在onDestroy中)
mAudioManager.abandonAudioFocus(mAudioFocusListener);
参考资料:http://blog.csdn.net/thl789/article/details/7422931
好文,通俗易懂
3.拖动Seekbar使MediaPlayer播放指定position的音乐
思路:监听Seekbar
具体实现:
1.定义seek方法
private void seek(int pos){
if(mPlayer != null){
mPlayer.seekTo(pos);
}
}
2.初始化SeekBar时,设置监听
mProgressBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// end touch SeekBar
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// start touch SeekBar
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
if(fromUser){
seek(progress);
}
}
});