600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > Android 音乐播放器的实现(三)Service的实现

Android 音乐播放器的实现(三)Service的实现

时间:2023-01-18 11:28:44

相关推荐

Android 音乐播放器的实现(三)Service的实现

Android 界一直流传着一句话,想学习Service, 那么你就要写一个音乐播放器。

为什么要用 Service?

Service 是运行于幕后的,它并不轻易见人,而正巧,音乐也是只闻其声不见其人的,相信这就是它们在一起的原因。

大家都知道,从Activity中跟Service交互有两种方式:

1)startService。在Activity 中直接调用 startService的方法,我们就可以在后台看不见的地方(但还是在同一个进程里)创建一个叫Service 的东西,它能够在后面静悄悄地执行类似下载的任务,也能够热热闹闹地唱起“苍茫的天涯是你的爱...”,但是这种方式呢,我们就只能跟它说,“Service,做这件事吧”,而没办法在它做一半的时候跟它说,“Service,别做这事了,做那一件事吧”(其实也可以,但是每次都要重新创建一个Intent,里面定义我们要做的事情,然后再次调用startService,让它重新再做,但我觉得,这不科学)。

2)bindService。我们也可以通过 bindService的方法来将Activity 跟 Service 绑定在一起,为什么绑定Service了之后就能够随时叫Service做事了呢?因为通过绑定,从Service返回了一个继承于Binder的类给Activity,而通过这个继承类,可以在里面定义一些交互的回调函数,那么Activity就可以通过这些方法来随时告诉Service要做些啥事了,这才叫交互嘛。

那么,音乐播放器肯定是要用后面这种 bindService的方法了啊,因为我们要交互啊。先看一下界面:

在列表界面上和歌词界面上有着不同的控制按钮,比如向前向后,模式改变,播放暂停等,所以我们得想想怎么去设计Service。

如何设计Service?

我把 Service 分成三种情况: 1)要响应 Activity 中按钮的控制; 2)Service中自己要控制的逻辑,比如一首歌播放完之后,要自动播放下一首等; 3)要能够主动地去通知Activity。

第一种情况,其实就是我们要在Binder中定义的接口啦,响应列表界面的唱停前后和模式变换。

class NatureBinder extends Binder{/*** 唱吧,有人想听*/public void startPlay(int currentMusic, int currentPosition){}/*** 别唱了*/public void stopPlay(){}/*** 后一首*/public void toNext(){}/*** 前一首*/public void toPrevious(){}/*** 有人改变模式了,我得把它记下来 */public void changeMode(){}/*** 告诉别人,你现在到底是顺序播放,还是随机乱弹* MODE_ONE_LOOP = 1;* MODE_ALL_LOOP = 2;* MODE_RANDOM = 3;* MODE_SEQUENCE = 4; * @return*/public int getCurrentMode(){}/*** 告诉调用者,到底有没有在做事。。。* @return*/public boolean isPlaying(){}/*** 要告诉调用者,当前播哪首歌了,歌多长啊*/public void notifyActivity(){}/*** 有人拖动Seekbar了,要告诉service去改变播放的位置* @param progress*/public void changeProgress(int progress){}}

那么第二种情况,就是servcie本身的逻辑控制了,其实主要的逻辑是当一首歌播放完了,它得自己去判断下一首要播什么,还有没有得播啊,所以我们要实现MediaPlayer的OnCompletionListener方法,在这里,我们要实现下一步该怎么做,继续播呢,还是停下来,要不要通知列表界面,我换歌了。。。

mediaPlayer.setOnCompletionListener(new OnCompletionListener() {@Overridepublic void onCompletion(MediaPlayer mp) {...});}

而第三种情况,就是怎么去通知列表界面了。在这里是通过发送广播的方式,而Activity中会注册相应的广播过滤器来接收Service中发送出去的消息,比如歌曲播放的进度,换歌了之类的。下面的代码是告诉前台,我现在播到哪个位置了,你给我更新一下进度条的位置。

private void toUpdateProgress(){if(mediaPlayer != null && isPlaying){int progress = mediaPlayer.getCurrentPosition();Intent intent = new Intent();intent.setAction(ACTION_UPDATE_PROGRESS);intent.putExtra(ACTION_UPDATE_PROGRESS,progress);sendBroadcast(intent);handler.sendEmptyMessageDelayed(updateProgress, 1000);}}

而相对应的,我们在Activity中,会接收到这样的广播,从而做相应的更新,当然,也别忘了要注册对应的Action,不然可收不到。代码如下:

private void registerReceiver(){progressReceiver = new ProgressReceiver();IntentFilter intentFilter = new IntentFilter();intentFilter.addAction(NatureService.ACTION_UPDATE_PROGRESS);...registerReceiver(progressReceiver, intentFilter);}//上面是注册广播,下面是接收广播,最后别忘了,要注销广播...class ProgressReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if(NatureService.ACTION_UPDATE_PROGRESS.equals(action)){int progress = intent.getIntExtra(NatureService.ACTION_UPDATE_PROGRESS, 0);if(progress > 0){currentPosition = progress; // Remember the current positionpbDuration.setProgress(progress / 1000);}...}}

既然已经把Service 该干什么都想好了,那么很显然下一步,就是来调用Service了嘛。

Service该怎么用?

废话!当然是在Activity中调用了。没错,就是这样,在Activity中我们通过BindService来获得一个Binder,然后就可以通过Binder来跟Service眉来眼去地交流了。

private NatureBinder natureBinder;private ServiceConnection serviceConnection = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {natureBinder = (NatureBinder) service;}};private void connectToNatureService(){Intent intent = new Intent(MainActivity.this, NatureService.class);bindService(intent, serviceConnection, BIND_AUTO_CREATE);}

当然,也是有几步要走的: 1)创建一个ServiceConnection 对象,在其onServiceConnected方法中返回我们的Binder。 2)就是调用bindService了,将serviceConnection作为参数传进去。 就是这么简单,接下来,就可以拿binder来做事了。比如 播放:

natureBinder.startPlay(currentMusic,currentPosition);

暂停:

natureBinder.stopPlay();

下一首:

natureBinder.toNext();

是的,就是这样。 差点忘了,请点击 源码下载:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。