基于Service的音乐播放器
开发思路
播放器音乐由后台运行的Service组件负责播放,当后台的播放状态发生改变时程序通过发送广播通知前台Activity更新界面;当用户操作前台界面时,系统将通过发送广播通知后台Service来改变播放状态。
程序包括两个BroadcasetReceiver(广播接收器)和一个service服务
一个广播接收器用于接收播放状态发生改变的广播
一个广播接收器用于接收歌曲播放完成时发送的广播
MainActivity:ActivityReceiver广播接收器用于接收来自Service的广播
MusicSerice(音乐播放服务):ServiceReceiver广播接收器用于接收Activity的广播
开发步骤
文件放置位置
- MP3文件位置
打开res文件夹:
res>New>Android resource directory:
弹出提示框New Resource Directory,在Resource type栏选择raw,如下图所示,然后点击OK:
即可创建raw文件夹,用于存放MP3文件,我们可以将音乐文件直接复制存放在此文件夹下面。
- 图片位置
可以直接存放在res文件夹下面的drawable文件夹:
也可以新建drawable-mdpi文件夹存放项目用到的图片,这里存放在drawable-mdpi里面。
Activity界面布局
在Activity中内嵌一个广播接收器ActivityReceiver,用于接收来自Service的广播。
// 定义一个广播接收器
public class ActivityReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
int update = intent.getIntExtra("update",-1);
int current = intent.getIntExtra("current",-1);
if(current>=0) {
title.setText(titles[current]);
author.setText(authors[current]);
}
switch (update) {
case 0x11:
play.setImageResource(R.drawable.play);
break;
case 0x12:
play.setImageResource(R.drawable.pause);
break;
case 0x13:
play.setImageResource(R.drawable.play);
break;
default:
break;
}
}
}
定义一个内部类,用来监听点击事件,在点击事件中发送广播:
private class MyListener implements View.OnClickListener {
public void onClick(View v) {
Intent intent = new Intent("com.example.leseul.ServiceReceiver");
switch (v.getId()) {
case R.id.play: // 点击播放按钮
intent.putExtra("control",1);
break;
case R.id.stop: // 点击暂停按钮
intent.putExtra("control",2);
break;
default:
break;
}
sendBroadcast(intent); // 发送广播
}
}
声明的变量和onCreate方法:
private ImageButton stop,play; // 用于获取暂停和开始按钮元素
private TextView title,author; // 用于获取音乐标题和作者文本元素
private ActivityReceiver activityReceiver;
private String[] titles = new String[]{"Color Blind","可乐"}; //保存音乐名称
private String[] authors = new String[]{"Matt B","赵紫骅"}; //保存作者名称
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
stop = (ImageButton) findViewById(R.id.stop);
play = (ImageButton) findViewById(R.id.play);
title = (TextView) findViewById(R.id.title);
author = (TextView) findViewById(R.id.author);
MyListener myListener = new MyListener();
play.setOnClickListener(myListener);
stop.setOnClickListener(myListener);
//注册广播接收器
activityReceiver = new ActivityReceiver();
IntentFilter intentFilter = new IntentFilter("com.example.leseul.ActivityReceiver");
registerReceiver(activityReceiver, intentFilter); //进行关联
//初始化
Intent intent = new Intent(MainActivity.this,MusicService.class); //显示调用
startService(intent); //启动服务
}
音乐播放服务
在服务中内嵌一个广播接收器ServiceReceiver,用于接收来自Activity的广播:
//广播接收器
public class ServiceReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
// 接收到了广播
int control = intent.getIntExtra("control",-1);
switch (control) {
case 1:
if(status == 0x11) { // 未播放,让其播放
prepareAndPlay(current); // 播放
status = 0x12;
} else if(status == 0x12) {
mediaPlayer.pause(); // 停止
status = 0x13;
}else if(status == 0x13) {
mediaPlayer.start();
status = 0x12; // 变成播放状态
}
break;
case 2:
if(status == 0x12 || status == 0x13) {
mediaPlayer.stop();
status = 0x11;
}
break;
default:
break;
}
Intent sendIntent = new Intent("com.example.leseul.ActivityReceiver");
// 状态设置
sendIntent.putExtra("update",status);
sendIntent.putExtra("current",current); // 当前播放哪一首歌
sendBroadcast(sendIntent); // 发送广播
}
}
编辑广播接收器的业务逻辑处理,写一个播放音乐的方法:
// 准备播放音乐
public void prepareAndPlay(final int index) {
try{
mediaPlayer = MediaPlayer.create(this,musics[current]);
// 事件监听,音乐是否播放完成
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
// 播放完成,则播放下一首
current++;
if(current == musics.length) { // 超过边界了
current = 0;
}
Intent sendIntent = new Intent("com.example.leseul.ActivityReceiver");
sendIntent.putExtra("current",current);
sendBroadcast(sendIntent);
prepareAndPlay(current); // 播放下一首
}
});
if(mediaPlayer!=null) {
mediaPlayer.stop();
}
mediaPlayer.prepare();
mediaPlayer.start();
} catch (Exception ex) {
ex.printStackTrace();
}
}