功能
①按下home键回到桌面时,音乐仍然可以播放,同时系统通知栏显示当前音乐播放的状态;
②点击App界面的按钮,可控制音乐播放的暂停继续,同时系统通知栏播放状态作相应改变;
③点击系统通知栏按钮控制音乐播放暂停,同时App界面播放状态作相应调整;
④App播放界面销毁时,关闭音乐,清除通知栏对应信息(即播放的控制View) —— 关系到startService()是否需要调用
思路
* 先实现service后台播放。
Activity通过bindService()方式可以调用Service中的方法,进而操作后台任务【因为项目需要,按下返回键销毁界面时,音乐 停止播放,也就是说该任务并不是一直存在的,所以本篇并没有添加startService(),如有需要,直接添加该句代码即可】
* 通知栏的显示、以及通知栏与界面的互操作【涉及到Broadcast,我这里是动态广播,因为项目需求】
实现步骤
小提示:本篇是基于网络音乐进行相关操作的,如果是本地音乐,操作差不多。如果看不太明白,可直接从(5)开始,代码注释比较清晰。
(1)绑定服务,并获取中间人IBinder对象
Intent intent=new Intent(this,MusicService.class); intent.putExtra("url",url); myConn = new MyConn(); //【1】绑定服务,并在MyConn中获取中间人对象(IBinder) bindService(intent, myConn,BIND_AUTO_CREATE);
其中,url为播放链接。MyConn类如下:
public class MyConn implements ServiceConnection{ @Override public void onServiceConnected(ComponentName name, IBinder service) { //获取中间人对象 myBinder = (MusicService.MyBinder) service; } @Override public void onServiceDisconnected(ComponentName name) { } }
MusicService.MyBinder是我们定义的一个IBinder子类,用于操作数据的,比如控制音乐的播放、暂停、继续播放以及进度条SeekBar的定时更新等。
(2)补充上面的MyIBinder信息
如下,创建IBinder子类,以暴露音乐播放的相关方法。
public class MyBinder extends Binder implements MyOperation { @Override public void play() { //播放 mediaPlayer.start(); updateSeekBar(); } @Override public void pause() { //暂停 if (mediaPlayer.isPlaying()) { mediaPlayer.pause(); } } @Override public void moveon() { //继续播放 mediaPlayer.start(); } @Override public void rePlay() { //重新开始 mediaPlayer.start(); } /** * 更新进度条 */ private void updateSeekBar() { //开启线程发送数据 new Thread() { @Override public void run() { while(!isStopThread){ try { int currentPosition = mediaPlayer.getCurrentPosition(); /* 发送数据给activity */ // //方法1,通过handler。但是这样有好多静态变量 // Message message = Message.obtain(); // message.what=3; // message.arg1=currentPosition; // MainActivity.handler.sendMessage(message); //方法2,通过广播 //方法3,使用EventBus实现 EventBus.getDefault().post(new UpdateUI(currentPosition,3)); Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } @Override public long getCurrentPosition() { return 0; } /** * 跳转到指定位置 * @param position */ @Override public void seekToPosition(int position) { mediaPlayer.seekTo(position); } }
其中,MyOperation封装了项目所需的基本,代码如下:
interface MyOperation { public void play();//播放 public void pause();//暂停 public void moveon();//继续 public void rePlay();//重新开始 public void seekToPosition(int position);//跳到相应位置 // public long getDuration();//获取视频长度 public long getCurrentPosition();//获取当前播放位置 }
(3)接下来就是在绑定服务的时候,返回该IBinder对象用于操作数据了。
Service具体代码如下(省略了MyIBinder类,其具体代码在上面已有贴出):
package qian.com.mymusicplayer; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer