上一篇文章 Android音乐播放器 -- 实现框架 说到 MediaPlayer Service 就是音乐播放器的”中部枢纽“,为什么这样说,主要有两点
1. MediaPlayer Service (简称MPS ) 负责整个音乐播放器的协调一致,比如,在播放列表显示当前播放的歌曲和播放详情显示的内容必须一致,这个就需要MPS来协调
2. MPS肩负起音乐播放器最本质的工作 -- 播放音乐 , 使用MPS 进行音乐播放,就算播放器在后台运行,仍然可以继续播放。
MPS包含下面三个模块内容
1. 接收来自Activity的播放请求
@Override
public int onStartCommand(Intent intent, int flag, int startId) {
Log.e(TAG, "onStartCommand");
//判断当前播放列表类型
type0 = intent.getIntExtra("TYPE",-1);
if(type0 == Common.PlayerType.TYPE_ALL) {
musicInfos = CursorHandle.getMusicInfos(MediaPlayerService.this);
type = type0;
} else if(type0 == Common.PlayerType.TYPE_ALBUM ) {
titleName = intent.getStringExtra("TitleName");
musicInfos = CursorHandle.getAlbumInfos(MediaPlayerService.this, titleName);
type = type0;
} else if(type0 == Common.PlayerType.TYPE_SINGER ) {
titleName = intent.getStringExtra("TitleName");
musicInfos = CursorHandle.getArtistInfos(MediaPlayerService.this, titleName);
type = type0;
}
path = intent.getStringExtra("url"); //歌曲路径
currentposition = intent.getIntExtra("listPosition", -1); //当前播放歌曲的在mp3Infos的位置
msg = intent.getIntExtra("MSG", 0); //播放信息
if (msg == Common.PlayerMsg.MSG_PLAY) { //点解列表 直接播放音乐
Intent sendIntent = new Intent(ACTION_UPDATE_INFO);
isPlaying = true;
sendIntent.putExtra("isPlaying", true);
sendIntent.putExtra("currentposition", currentposition);
sendIntent.putExtra("TYPE", type);
sendIntent.putExtra("TitleName", titleName);
// 发送广播,将被Activity组件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
PlayMusic(0);
} else if (msg == Common.PlayerMsg.MSG_PAUSE_RUSUME) { //暂停
PauseNResumeMusic();
} else if (msg == Common.PlayerMsg.MSG_PRIVIOUS) { //上一首
PreviousMusic();
} else if (msg == Common.PlayerMsg.MSG_NEXT) { //下一首
NextMusic();
} else if (msg == Common.PlayerMsg.MSG_CHANGE_PROGRESS) { //点击进度条 更新音乐服务
currentTime = intent.getIntExtra("progress", -1);
mHandler.removeMessages(1);
isPlaying = true;
//更新UI 主要是为了解决暂停点击seekbar 后 play button UI没更新问题
Intent sendIntent = new Intent(ACTION_UPDATE_INFO);
sendIntent.putExtra("isPlaying", isPlaying);
sendIntent.putExtra("currentposition", currentposition);
duration = mediaPlayer.getDuration();
sendIntent.putExtra("duration", duration);
sendBroadcast(sendIntent);
PlayMusic(currentTime);
} else if (msg == Common.PlayerMsg.MSG_PLAY_DETAIL) {
Intent sendIntent = new Intent(ACTION_UPDATE_INFO);
sendIntent.putExtra("isPlaying", isPlaying);
sendIntent.putExtra("currentposition", currentposition);
duration = mediaPlayer.getDuration();
sendIntent.putExtra("duration", duration);
sendBroadcast(sendIntent);
mHandler.sendEmptyMessage(1);
}
return super.onStartCommand(intent, flag, startId);
}
2. 播放功能实现
/**
* 播放音乐
*
* @param <span style="font-family: Arial, Helvetica, sans-serif;">current</span>
*/
private void PlayMusic(int current) {
try {
mediaPlayer.reset();// 把各项参数恢复到初始状态
mediaPlayer.setDataSource(path);
mediaPlayer.prepare(); // 进行缓冲
mediaPlayer.setOnPreparedListener(new PreparedListener(current));// 注册一个监听器
//mHandler.sendEmptyMessage(1); //更新时间UI
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 暂停与开始音乐
*/
private void PauseNResumeMusic() {
Intent sendIntent = new Intent(ACTION_UPDATE_INFO);
// 发送广播,将被Activity组件中的BroadcastReceiver接收到
sendIntent.putExtra("currentposition", currentposition);
duration = mediaPlayer.getDuration();
sendIntent.putExtra("duration", duration);
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
isPlaying = false;
sendIntent.putExtra("isPlaying", false);
mediaPlayer.pause();
} else {
isPlaying = true;
sendIntent.putExtra("isPlaying", true);
mediaPlayer.start();
}
sendBroadcast(sendIntent);
}
/**
* 上一首
*/
private void PreviousMusic() {
Intent sendIntent = new Intent(ACTION_UPDATE_INFO);
isPlaying = true;
sendIntent.putExtra("isPlaying", true);
sendIntent.putExtra("currentposition", currentposition);
// 发送广播,将被Activity组件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
PlayMusic(0);
}
/**
* 下一首
*/
private void NextMusic() {
Intent sendIntent = new Intent(ACTION_UPDATE_INFO);
isPlaying = true;
sendIntent.putExtra("isPlaying", true);
sendIntent.putExtra("currentposition", currentposition);
sendIntent.putExtra("TYPE", type);
sendIntent.putExtra("TitleName", titleName);
// 发送广播,将被Activity组件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
PlayMusic(0);
}
@Override
public void onDestroy() {
if (null != mediaPlayer) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
mHandler.removeMessages(1);
}
/**
*
* 实现一个OnPrepareLister接口,当音乐准备好的时候开始播放
*
*/
private final class PreparedListener implements OnPreparedListener {
private int currentTime;
public PreparedListener(int currentTime) {
this.currentTime = currentTime;
Log.e(TAG, "current1 = " + currentTime);
}
@Override
public void onPrepared(MediaPlayer mp) {
Log.d(TAG, "onPrepared and start music");
Toast.makeText(MediaPlayerService.this, "开始播放",
Toast.LENGTH_SHORT).show();
mediaPlayer.start(); // 开始播放
if (currentTime > 0) { // 如果音乐不是从头播放
Log.e(TAG, "current3 = " + currentTime);
mediaPlayer.seekTo(currentTime);
}
//更新时间
mHandler.sendEmptyMessage(1);
//更新 歌曲时间
Intent intent = new Intent();
intent.setAction(ACTION_MUSIC_DURATION);
duration = mediaPlayer.getDuration();
intent.putExtra("duration", duration); //通过Intent来传递歌曲的总长度
Log.e(TAG, "[Send Music Duration]duration = " + duration);
sendBroadcast(intent);
}
}
3. 发送广播,请求更新UI
/*
* 设置音乐播放完成时候的监听动作 更新UI
* */
mediaPlayer.setOnCompletionListener(new OnCompletionListener(){
public void onCompletion(MediaPlayer mp) {
currentposition++; //下一首位置
Log.e(TAG,"musicInfos.size() = " + musicInfos.size() );
if (currentposition <= musicInfos.size() - 1) {
Intent sendIntent = new Intent(ACTION_UPDATE_INFO);
sendIntent.putExtra("currentposition", currentposition);
sendIntent.putExtra("isPlaying", true);
isPlaying = true;
// 发送广播,将被Activity组件中的BroadcastReceiver接收到
sendBroadcast(sendIntent);
path = musicInfos.get(currentposition).getUrl();
PlayMusic(0);
}
}
MPS的大体功能介绍到这里,使用广播的方法进行构建,确实是一个非常好的学习机会,用过才会真正记牢,希望大家有兴趣多写写代码,做个播放器真心不错~
重要的事情,源码请猛戳 这里 下载
下篇文章 Android音乐播放器 -- 数据处理 会讲讲播发器使用的的数据结构,敬请期待~