参考官网:http://developer.android.com/reference/android/app/Service.html
1.what is service:
- 两个不是:
-service不是一个单独的进程,运行在应用程序所属的进程里——除非:AndroidManifest.xml声明service时显示属性:android:process=":remote"
-service不是一个单独的线程,但是可以脱离主线程工作——为了避免“应用程序无响应”的错误
默认:service在后台运行在主线程里(UI线程)
- 两个是:
-service可以是:应用程序告诉系统,它想放一些东西在后台运行。这时的service由系统管理,直到有人(包括service自己)显式调用stopService或stopSelf把service停止。——startService
-service可以是:应用程序向别的应用程序展示一些功能。这时service长期绑定在这个应用上,可以与这个应用进行交互。——bindService
2.生命周期:
可以看出,有两种方式获得service,一是startService,一是bindService
- startService方式:
-startService()开启服务:service先onCreate,然后onStartCommand。如果再次startService,service只执行onStartCommand,不再执行onCreate
-stopService()或stopSelf()停止服务:service进入onDestroy。无论service被startService()多少次,由于并没有执行onCreate,说明每次start的都是同一个service,因此只需要一次onDestroy就把这个service停止了。
- bindService方式:
-bindService()绑定服务:如果service没有还没有create,那么进入onCreate,然后onBind。否则直接进入onBind。
-unbindService()解除绑定:如果service没有别的应用绑定,只是自己退出而已。如果是最后一个关联的应用解除绑定,那么service进入onUnbind。当这个service没有应用绑定,也没有应用start,那么这个service就onDestroy。
3. bindService方式:
bindService方式有点罗嗦,这里单独讲下。
- 连接:
由于bindService是application和service建立了一个连接,为了双方的交互,所以客户端application需要提供一个ServiceConnection的对象。提供两个函数:onServiceConnected和onServiceDisconnected,分别表示当连接建立和断开时回调。因此,可以重写这两个函数来实现自定义操作。
- 那么双方究竟如何交互的呢:
客户端bindService后,服务器端会进入onBind。onBind返回一个IBinder对象,这个对象会返回给客户端。返回到哪里呢?就是onServiceConnected的参数IBinder。可以输出service端和client端的这两个IBinder,可以看到是一样的。也就是说,双方靠这个IBinder对象进行交互!
怎么交互呢?
-服务端自定义一个类继承Binder,这个Binder类中自定义一些方法。
-onBind中将这个Binder自定义类的对象返回。
-客户端的onServiceConnected函数中,从参数得到这个IBinder对象。
-客户端可以直接使用这个IBinder对象调用服务端Binder类的自定义方法。这样就客户端就可以调用服务端的方法啦!
4. Remote Service
service和client在同一个进程内,就是localservice,不在同一个进程,就是remoteservice。
- 定义service是remote service:
AndroidMenifest.xml中声明Service时,添加属性,android:process=":remote"
- startService与BindService:
start一个remote Service和start一个local Service没有本质区别。因为application和service不需要交互,start之后各自运行各自的,所以很简单, 下文不再讲述。
bind一个remote Service和bind一个local Service不同。local service可以返回一个IBinder对象供client使用,从而完成两者的交互。remote service则需要使用AIDL方式来完成交互。
- client与remote service进行交互:
(1)AIDL方式:AIDL——android interface definition language
原理:
公共端:定义接口文件myinterface.aidl,这个接口是公共的,要放在service和client的src下。
service:定义stub实现myinterface中声明的方法。stub相当于代理。
client端:可以远程调用myinterface.aidl中声明的方法,这些方法的实际执行是在service端。
那么service和client是如何联系起来的呢?和local service一样,通过onBind函数的返回值!
首先:service顶一个接口Stub类型的对象,实现myinterface.aidl中的方法。
接着:service在onBind中返回Stub类型的对象,这时这个对象是IBinder类型。
然后:client在ServiceConnection的onServiceConnected函数中的参数获得service传过来的IBinder对象。
最后:client使用myinterface.stub.asInterface(IBinder对象)函数将这个IBinder转化为AIDL接口类型。
可以看到,remote service和local service类似,使用这个共同的IBinder对象交互!不同的是,需要把这个对象在IBinder类型和AIDL接口类型之间做下转换。
local service中,client调用service提供的方法,这些方法的定义就在IBinder类中。即,声明和定义都在service端。
remote service中,client调用service提供的方法,这些方法的声明在它们共有的AIDL文件里,定义在service端的stub对象里。
(2)Messenger方式:
原理:
service:定义Handler处理client请求,使用这个Handler创建Messenger_s_receive,使用这个Messenger_s_receive创建IBinder对象,将这个对象在onBind函数中返回。
client端:ServiceConnection的onServiceConnected函数的参数中获得service传过来的IBinder对象,始终这个IBinder对象创建Messenger_c_send。
——Messenger_s_receive用于service接收消息,Messenger_c_send用于client发送消息
client端:定义Handler处理service请求,使用这个Handler创建Messenger_c。使用Messenger_c_send向service发送消息时,注册Messenger_c。
service:Handler中处理client请求,保存client发送的消息为“注册”的Messenger(就是Messenger_c),使用这个保存的Messenger向client端发送消息。
——Messenger_c用于service向client发送消息,也用于client从service接收消息
总结:无论是AIDL方式,还是Messenger方式;无论是local service还是remote service。service和client的联系最终都是通过IBinder对象连接起来的。因此,service端的onBind函数的返回值非常重要!归根到底,进程间的通讯是由Binder实现的!