ref:http://developer.android.com/guide/components/bound-services.html?
前言
重新学习这一项技术,主要的原因,是因为以前没有好好的学,那时总觉得作品能动,能完成工作就好了,而这种得过且过的想法,大大地影响了我的技术程度,也因此,在这个这个博客里,有许多的复习心得。有幸得到一位前辈的指导,指出,若只是学习,而无实际应用,这样进步会较少,因此,最好要多看源码,并且自己多尝试多实践,这样学习一万小时,应该能有小进步,因此开始了 Bound Service相关学习/复习工作。
Bound Service
「Bound Service是 Client-Server Interface 中的服务端,一个 Activity 可以透过 Bound Service 绑定一个服务,收发讯息,甚至进行进程间通讯。」Service类是一个 Abstract Class,而 Bound Service实现了 Service类,并实现了 onBind()方法,Activity 才能和 Service进行沟通。 所以,我们先从简单的例子--让一个 Activity 绑定一个 Service,让 Service 能够为 Activity
提供服务,同时,我已将练习的相关代码提交至 GitHub上(https://github.com/shanwu/InterProcessCommPractice),有不同的分枝分别代表不同的例子,这样可以使用 Github上的分枝比较功能()比较不同方法间的差异。
master 分枝:进程内通讯,代表的是官网 Extending the Binder class的例子。
ipc_messanger_example:跨进程通讯,代表的是官网 Using a Messenger的例子(抱歉 branch 名英文拼错 Orz)
ipc_messenger_example_bidirection:同上,但是其为 Service, Activity 双向互传的例子。
ipc_aidl_example:跨进程通讯,简单的 aidl 使用例子。
Extending Binder Service
客户端的 Activity 可以透过呼叫 bindService()方法和服务端的 Service建立连结,连结建立的时候,会先调用 Bound Service的 onBind() 方法,再来调用 onServiceConnected(),而如果是需要移除连结的话,便调用 unbindService()方法,此时Bound Service会直接调用 onDestory(),然後服务结束。代码如下:
在Bound Service写一个继承 Binder的类-LocalBinder,主要是在进程内通讯时,在 onBind()的时候,能够用方法来返回 Bound Service的对象:
public class LocalBinder extends Binder { public Service getService() { return WorkerService.this; } }
宣告一个 LocalBinder的私有全局变量
public class WorkerService extends Service { private final IBinder mBinder = new LocalBinder();
同时覆写 onBind()方法
@Override public IBinder onBind(Intent intent) { Log.d("guang","onBind"); return mBinder; }
而在Activity端,我们需要使用 bindService()来进行绑定 Bound Service的工作
@Override public void onClick(View v) { final int id = v.getId(); switch (id) { case R.id.btn_start: Intent intent = new Intent(MainActivity.this, WorkerService.class); bindService(intent, mServiceConn, Context.BIND_AUTO_CREATE); break;
同时我们需要将接口 ServiceConnection的方法覆写,在连结开始的时候,iBinder便是onBind所返回的 IBinder类变量,所以我们将它强转为LocalBinder,然後调用LocalBinder里的方法以取得 Bound Service 的对象,将它在於全局变量中,之後便可以调用他的方法。这边要注意的是 onServiceDisconnected一般情况下不会调用,只有在 Service发生异常导致连结结束才会调用。
mServiceConn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { WorkerService.LocalBinder lBinder = (WorkerService.LocalBinder) iBinder; mService = (WorkerService) lBinder.getService(); Log.d("guang","onServiceConnected"); mIsBind = true; } @Override public void onServiceDisconnected(ComponentName componentName) { Log.d("guang","onServiceDisconnected"); mIsBind = false; } };
调用它的方法,使 Bound Service 做事,它可以是播放音乐,或是执行其它不需要 UI 界面的工作。
case R.id.btn_sing: if (mIsBind) { mService.makeSingingService(); } break;
这样基本上就是本篇的重点了~全部代码均可自 GitHub取得~