之前的博客Android 7.0 ActivityManagerService(6) Service相关流程分析,介绍了Service相关的源码流程。
由于源码流程过长,不太容易从整体上把握Service的主要逻辑,因此在这边博客中总结一下Service相关的流程。
其实上,这篇博客也可以看做是对Service相关流程的概述。
按照Service的启动方式,通常情况下,可以将Service细分为Bounded Service和Unbounded Service。
Bounded Service是指,客户端以bindService的方式,启动的服务;
Unbounded Service是指,客户端以startService的方式,启动的服务。
当然这并不是一种严格的定义,一个客户端以startService的方式启动服务后,该服务同样可以被另一个客户端以bindService的方式绑定。
不过,我们可以按照这种粗略的划分方式,分析一下Service的基本流程。
一、Unbounded Service概述
1.1 启动的基本流程
如上图所示,对于Unbounded Service而言,客户端调用startService后,对应的Intent信息将被发送给AMS。
AMS负责根据Intent中的组件信息,找出客户端希望通信的Service。
若Service没有启动,甚至Service所在的进程都没有启动,那么AMS将负责启动Service所在的进程,然后通过反射创建出Service。
当Service创建完毕后,AMS负责回调Service生命周期中的onCreate函数。
待Service完成启动后,AMS将进一步回调Service的onStartCommand函数,将Intent递交给其处理。
若Service已经启动了,那么在之后的通信中,当客户端再次调用startService传递Intent给Service时,
AMS仅会回调Service的onStartCommand函数进行处理。
从以上的通信过程可以看出,对于Unbounded Service而言,AMS相当于一个路由器。每次客户端试图与Service通信时,都必须将Intent递交给AMS,然后由AMS转发给Service。
1.2 结束的基本流程
对于Unbounded Service而言,一旦启动后,将一直在后台运行(处于被系统或用户kill外),
直到客户端调用stopService停止服务,或Unbounded Service主动调用stopSelf停止。
客户端调用stopSerivce发送的请求,也将发送给AMS。
AMS收到请求后,将回调Service的onDestroy函数,并清除记录的Service对应的信息。
二、Bounded Service概述
2.1 启动的基本流程
与Unbounded Service相比,Bounded Service的通信方式要相对复杂一些。
整个通信过程大概可以简化为下图:
1)客户端与服务端通信前,首先需要调用bindService接口,发送绑定Service的请求。
bindService接口需要的参数,除了用于描述待绑定服务的Intent外,还有客户端实现的ServiceConnection和描述绑定策略的flag。
bindService函数,会将Intent信息、ServiceConnection对应的Binder通信服务端代理及flag等信息一并递交给AMS处理。
与Unbounded Service一样,AMS收到请求后,将根据Intent信息检索出待绑定的Service。
2)如果Service没有启动,甚至Service所在的进程都没有启动,那么AMS将检测flag信息中是否包含Context.BIND_AUTO_CREATE。
只有包flag中含该标志位时,AMS才会创建Service对应的进程,然后反射加载Service,并依次调用Service的onCreate和onBind接口。
3)当Service的onBind接口调用完毕后,Service所在进程将通知AMS发布服务,即调用AMS的publishService接口。
在此过程中,Service对应的Binder通信服务端代理将被递交给AMS。
AMS将建立起Intent信息与Service Binder通信服务端代理之间的映射。
这样当其它客户端以同样的Intent绑定Service时,AMS可以直接查找出Intent对应的Service Binder通信服务端代理。
例如,上图的Client 2使用与Client 1相同的Intent绑定服务时,AMS不会调用Service的onBind接口,
而是查找出之前存储的Service Binder通信服务端代理。
4)AMS得到Service的Binder通信服务端代理后,将信息发送给 ServiceConnection对应的Binder通信服务端。
5)ServiceConnection的Binder通信服务端收到信息后,回调ServiceConnection的onServiceConnected接口。
于是,客户端成功获取到Service端的服务代理接口,可以通过开始通过该接口向Service发送业务请求。
此后,业务级的通信不再依赖于AMS,仅依靠底层的Binder驱动即可。
从以上的通信过程可以看出,对于Bounded Service而言,AMS相当于一个DNS服务器。
1)当客户端将绑定Service的请求发送给AMS时,
AMS需要查询自己是否有Service对应Binder服务端代理的记录信息。
这一步相当于,主机将域名发往DNS服务器,请求解析(假设主机本地没有保存信息)。
2)如果AMS存在该记录信息,就直接向客户端返回该信息。
这一步相当于,DNS服务器中保存了对应的IP地址,
那么DNS就直接将IP地址返回给主机。
3)如果不存在该信息,AMS就与Service通信,获取Service对应Binder服务端代理信息。
然后,AMS在本地存储该信息,并将信息返回给客户端。
这一步相当于,DNS服务器向自己的父节点发送请求,查询域名对应的信息。
一旦查询到结果后,DNS服务器就保存该信息,并将结果返回给主机。
2.2 结束的基本流程
与Unbounded Service一样,Bounded Service一旦启动后,同样将一直在后台运行。
客户端必须主动调用unbindService与Service解绑。客户端发送的解绑请求,同样将发送给AMS处理。
AMS收到解绑请求后,会清除一些记录信息,然后回调Service的onUnbind接口。
由于一个Service可能被多个客户端绑定,只有所有的客户端全部解绑后,AMS才会回调Service的onDestroy函数。
当Service的onDestroy被调用后,AMS才会统一回调所有ServiceConnection的onServiceDisconnected函数。
三、总结
以上是从源码中抽象出来的,Service相关的基本流程。
详细的代码分析可以参考Android 7.0 ActivityManagerService(6) Service相关流程分析。