service启动流程(Service 绑定流程)

本文目录
- Service 绑定流程
- 请描述bindService()启动服务的流程,并说明如何调用服务里自定义的方法
- Android重学系列 Service 启动和绑定原理
- Android四大组件的工作过程
- Android 10.0 ActivityManagerService的启动流程
- WMS 启动流程
- Android系统启动-SystemServer进程
- Android输入法IMMS服务启动流程(3)(启动IMS应用)
Service 绑定流程
Service 服务有两种方式启动,1, startService() 方法启动,2,bindService() 方法绑定。
bindService() 方法,返回一个 Binder,负责和 Service 通信。
多次执行 bindService() 绑定方法,onCreate() 和 onBind() 方法只执行一次。
可以同时使用两个启动方法,例如,先 startService() 方法启动服务,执行生命周期方法,onCreate() 和 onStartCommand() 方法,再绑定,onBind() 方法。
解除绑定 onUnBind(),停止服务,onDestroy() 方法。
ContextWrapper 装饰者类 bindService() 方法,委托内部 ContextImpl 类 bindService() 方法。
bindServiceCommon() 方法,访问 Ams 服务。
sd 是 IServiceConnection 对象,系统为 Ams 服务设定的入参,跨进程通信 (不是 ServiceConnection),回调 App, 在 IServiceConnection.aidl 文件中定义。
Ams 服务 bindService() 方法。
LoadedApk 类 getServiceDispatcher() 方法,获取 IServiceConnection。
LoadedApk 类 内部保存 ServiceConnection 和 ServiceDispatcher ( LoadedApk 内部类)的 ArrayMap。
InnerConnection 类,继承 IServiceConnection.Stub,持 ServiceDispatcher 弱引用。
Binder 类型,Ams 服务回调 App 的实现类,进程间通信的服务端,IServiceConnection 业务实现,实现方法是 connected() 。
在 Ams 服务中,涉及相关类是 ActivityManagerService 和 ActiveServices 类。
在 realStartServiceLocked() 方法,通过 IApplicationThread 代理,回调 App 进程 scheduleCreateService() 方法,生命周期方法 onCreate()。
在 requestServiceBindingLocked() 方法,回调 App 进程 scheduleBindService() 方法,执行 Service 的 onBind() 和 ServiceConnection 类 onServiceConnected() 方法。
1,生命周期 onCreate() 方法 和 Service 启动流程一样。
2,scheduleBindService() 方法,向主线程发送消息,执行 handleBindService() 方法,(H 类处理 BIND_SERVICE 消息)
根据 token 查找已创建的 Service 对象,执行 Service 类 onBind() 方法,返回 IBinder 对象(+业务类型),Service 类服务端实现业务接口。
publishService() 方法,发布 IBinder 到 Ams,再通过 IServiceConnection 代理通知客户端。
ConnectionRecord 内部 conn,InnerConnection 类型,Ams 服务通过它访问 App 进程,调用 InnerConnection 的 connected() 方法,将 Binder 返回。
内部弱引用 ServiceDispatcher 的 connected() 方法,
ServiceDispatcher 构造方法传入 Handler,即从 ActivityThread 获取的 H 类。
RunConnection 任务,执行 doConnected() 方法。
执行 ServiceDispatcher 内部 ServiceConnection 的 onServiceConnected() 方法,用户自己实现。
只有onBind() 返回 Binder 不空时,才会调用 onServiceConnected() 方法。
ActivityManager.getService() 方法,客户端 ActivityManagerService 代理,执行 Ams 服务 bindService() 方法。
委托给 Ams 内部的 ActiveServices 类,以下都是该类的方法。
调用 bringUpServiceLocked() 方法。
调用 realStartServiceLocked() 方法,通过 scheduleCreateService() 方法回调 App 进程,创建 Service,生命周期 onCreate() 方法,然后,设置 created 标志,再执行 requestServiceBindingLocked() 方法,它回调 App 进程的 scheduleBindService() 方法,回传参数 IBinder ( Ams 的 ServiceRecord 记录),在 App 进程,发送 BIND_SERVICE 绑定消息到 ActivityThread 的 H 处理。
注意,sendServiceArgsLocked() 方法,用于回调 App,执行 onStartCommand() 方法,但需要 ServiceRecord 有 startRequested 标志,以及 pendingStart 列表不空,显然,即使多次 bindService(),上面走进了 sendServiceArgsLocked() 方法,也不会去执行 onStartCommand()。
向 Ams 服务注册绑定的服务类,通过 ApplicationThread 类实现 App 通知。
如果服务未创建,首先通知 App 生成服务实例, 生命周期 onCreate() 方法。
多次 bindService() 时,onCreate() 和 onBind() 只执行一次。
服务绑定成功,将 Binder 发布到 Ams 服务,Ams 再利用 IServiceConnection 业务接口跨进程将服务已经连接的消息通知在 Activity 中自定义的服务连接对象 ServiceConnection,返回它 Binder。
任重而道远
请描述bindService()启动服务的流程,并说明如何调用服务里自定义的方法
我们有两种方式启动一个Service,他们对Service生命周期的影响是不一样的。
1 通过startService
Service会经历 onCreate --》 onStart
stopService的时候直接onDestroy
如果是 调用者 直接退出而没有调用stopService的话,Service会一直在后台运行。
下次调用者再起来仍然可以stopService。
2 通过bindService
Service只会运行onCreate, 这个时候 调用者和Service绑定在一起
调用者退出了,Srevice就会调用onUnbind--》onDestroyed
所谓绑定在一起就共存亡了。
注意:Service的onCreate的方法只会被调用一次,
就是你无论多少次的startService又 bindService,Service只被创建一次。
如果先是bind了,那么start的时候就直接运行Service的onStart方法,
如果先是start,那么bind的时候就直接运行onBind方法。如果你先bind上了,就stop不掉了,
只能先UnbindService, 再StopService,所以是先start还是先bind行为是有区别的。
Android中的服务和windows中的服务是类似的东西,服务一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。
服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。
这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,
即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。
如果打算采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,
接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,
但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。
如果打算采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,
接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,
接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,
多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。
如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()--》onDestroy()方法.
onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。这个时候调用者会和Service绑定在一起,但onBind只能一次,不可多次绑定。
在Service每一次的开启关闭过程中,只有onStart可被多次调用(通过多次startService调用),其他onCreate,onBind,onUnbind,onDestory在一个生命周期中只能被调用一次。
由于Android 中的Service使用了onBind 的方法去绑定服务,返回一个Ibinder对象进行操作,而我们要获取具体的Service方法的内容的时候,我们需要Ibinder对象返回具体的Service对象才能操作,所以说具体的Service对象必须首先实现Binder对象,这个样子的话我们才能利用bindService的方法对Service进行绑定,获取Binder对象之后获取具体的Service对象,然后才获取Service中的方法等等。
与采用Context.startService()方法启动服务有关的生命周期方法
onCreate() --onStart() --onDestroy()
onCreate()该方法在服务被创建时调用,该方法只会被调用一次,无论调用多少次startService()或bindService()方法,服务也只被创建一次。
onStart() 只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。多次调用startService()方法尽管不会多次创建服务,但onStart() 方法会被多次调用。
onDestroy()该方法在服务被终止时调用。
与采用Context.bindService()方法启动服务有关的生命周期方法
onCreate()-- onBind() -- onUnbind() -- onDestroy()
onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用,当调用者与服务已经绑定,多次调用Context.bindService()方法并不会导致该方法被多次调用。
Android重学系列 Service 启动和绑定原理
我们已经了解了BroadcastReceiver的原理,我们再来看看四大组件之一的Service是怎么启动的,以及怎么运行的原理。
***隐藏网址***
启动Service的入口就是startService和bindService方法。我们先来看看startService在ContextImpl中做了什么。
文件:/ frameworks / base / core / java / android / app / ContextImpl.java
此时调用的就是AMS的startService方法。
mServices是一个ActiveServices对象。这个对象是在AMS的构造函数中初始化好的。
这里调用了ActiveServices的startServiceLocked。
文件:/ frameworks / base / services / core / java / com / android / server / am / ActiveServices.java
核心流程有如下三个:
注意这里addToStarting是一个比较关键的判断,addToStarting默认为false。
如果此时不是启动前台服务,则需要进一步进行处理。如果ProcessRecord为空或者curProcState大于PROCESS_STATE_RECEIVER这个优先级数值;也就是优先级更小。
为了避免此时App应用是没有任何的前台ui,或者App应用还没有声明。避免有的App通过startService进行应用的包活或者拉起应用。就会进行如下能够存在的最大后台服务数量,则放入mDelayedStartList中进行延时启动后台服务,现在直接返回了。
不然则说明能够允许启动后台服务, 就设置为addToStarting为true。
通过ComponentName也就是包名和类名查找ServiceRecord;通过Intent意图过滤找到ServiceRecord。·
核心方法是bringUpServiceLocked。如果bringUpServiceLocked返回了异常,就返回一个特殊的ComponentName对象。
addToStarting为true,说明此时是一个能够启动的后台服务,则ServiceRecord添加到mStartingBackground中。如果mStartingBackground的数量为0,则直接调用ServiceMap的rescheduleDelayedStartsLocked启动后台服务。
这几个关键的步骤,让我们依次的考察,先来看看scheduleCreateService中做了什么。
如果第一次启动就走第一个if的分支:
能看到和BroadcastReceiver的ANR思路一样,通过一个延时的Handler,如果达到时间了还没有移除这个Handler消息则报ANR异常。
这里根据启动前台和后台分为两种超时时间:
前台分别是10秒,后台服务不属于后台进程组(判断adj是否在SCHED_GROUP_BACKGROUND)是20秒,后台服务属于后台进程组 200秒。
把数据封装成CreateServiceData后,通过Handler调用如下方法:
透三点的核心原理可以看我写的的Application创建和BroadcastReceiver原理两篇文章。来看看Service中都做了什么?
很简单就是保存了传递过来的参数,值得注意的是这个IBinder对象其实就是指ServiceRecord对象。
接着执行Service.onCreate这个空实现的方法。
本质上还是调用了ActiveServices的serviceDoneExecutingLocked方法。
type是SERVICE_DONE_EXECUTING_ANON,所不会做更多的处理。 最后执行了serviceDoneExecutingLocked方法。
这个方法不断的循环遍历List《ServiceStartArgs》分发SERVICE_ARGS消息,这个消息通过主线程的Looper调用handleServiceArgs。
bindService在开发中用的不是很多,这里稍微提一下他的使用。
首先申明一个ServiceConnection对象,用于绑定服务端的Service。
调用bindService的方法绑定到某个Service中。当服务端的service成功回调onBind方法,我们只需要返回对应的Binder对象。就能使用调用bindService的客户端在ServiceConnection的onServiceConnected的回调中获得Binder对象。
之后就能通过这个Binder调用本进程或者其他进程的的方法了。实际上我们可以把这个过程看成一个多对多的服务-客户端模型。多个客户端通过Binder向多服务端Service通信,每一次我们都可以通过ComponentName判断不同服务返回来的Binder对象。
这里面很简单,和BroadcastReceiver的思路很像。动态注册的BroadcastReceiver会封装成一个ReceiverDispatcher,而这里把ServiceConnection封装成LoadedApk.ServiceDispatcher对象。
并且会把ServiceDispatcher作为value,ServiceConnection作为key缓存一个map中。并且以context为key,把这个临时的map作为value缓存起来。这样一个Context就映射有了多个ServiceDispatcher对象,也就可以注册多个监听被绑定Service状态的监听者了。
Android四大组件的工作过程
Service的启动流程和Activity类似,以下是Service的大致启动流程
Serice的绑定流程比startService的流程稍微要复杂一点,大概的时序图可以分为下面3个部分
广播的发送有几种:普通广播、有序广播和粘性广播,他们的发送/接收流程是类似的,因此只分析普通广播的实现。
1.广播的发送和接收, 本质就是一个过程的两个阶段. 广播的发送仍然开始于ContextImpl#sendBroadcase()方法, 之所以不是Context, 那是因为Context#sendBroad()是一个抽象方法. 和广播的注册过程一样, ContextWrapper#sendBroadcast()仍然什么都不做, 只是把事情交给了ContextImpl去处理。
2.ContextImpl里面也几乎什么都没有做, 内部直接向AMS发起了一个异步请求用于发送广播。
3.调用AMS#broadcastIntent()方法,继续调用broadcastIntentLocked()方法。
4.在broadcastIntentLocked()内部, 会根据intent-filter查找出匹配的广播接收者并经过一系列的条件过滤. 最终会将满足条件的广播接收者添加到BroadcastQueue中, 接着BroadcastQueue就会将广播发送给相应广播接收者。
5.BroadcastQueue#scheduleBroadcastsLocked()方法内并没有立即发送广播, 而是发送了一个BROADCAST_INTENT_MSG类型的消息, BroadcastQueue收到消息后会调用processNextBroadcast()方法。
6.无序广播存储在mParallelBroadcasts中, 系统会遍历这个集合并将其中的广播发送给他们所有的接收者, 具体的发送过程是通过deliverToRegisteredReceiverLocked()方法实现。deliverToRegisteredReceiverLocked()负责将一个广播发送给一个特定的接收者, 它的内部调用了performReceiverLocked方法来完成具体发送过程。
7.performReceiverLocked()方法调用的ApplicationThread#scheduleRegisteredReceiver()实现比较简单, 它通过InnerReceiver来实现广播的接收。
8.scheduleRegisteredReceiver()方法中,receiver.performReceive()中的receiver对应着IIntentReceiver类型的接口. 而具体的实现就是ReceiverDispatcher#InnerReceiver. 这两个嵌套的内部类是所属在LoadedApk中的。
9.又调用了LoadedApk$ReceiverDispatcher#performReceive()的方法.在performReceiver()这个方法中, 会创建一个Args对象并通过mActivityThread的post方法执行args中的逻辑. 而这些类的本质关系就是:
10.实现Runnable接口的Args中BroadcastReceiver#onReceive()方法被执行了, 也就是说应用已经接收到了广播, 同时onReceive()方法是在广播接收者的主线程中被调用的。
ContentProvider的启动过程和其他3大组件基本类似,都是通过AMS实现进程间的数据共享,这里主要列举一下 ContentResolver里的query方法到AMS的过程 和 AMS启动ContentProvider的过程
Android 10.0 ActivityManagerService的启动流程
我们讲完了SystemServer的启动过程,本节主要来讲解ActivityManagerService的启动过程。ActivityManagerService简称AMS,管理Activity行为,控制Activity的生命周期,派发消息事件,内存管理等功能。
ActivityManagerService启动由SystemServer中startBootstrapService启动
ATM启动最终调用的是ActivityTaskManagerService.Lifecycle.onStart()来启动ATM服务的
源码:ActivityTaskManagerService.java#Lifecycle.class
将ActivityTaskManagerInternal添加到本地服务的全局注册表中。
ActivityTaskManagerInternal为抽象类,其实现类为ActivityTaskManagerService#LocalService.class
构造函数初始化主要工作就是初始化一些变量,供之后的service,broadcast,provider的管理和调度
start中做了两件事
AMS的systemReady处理分为三个阶段
同时获取一些配置参数。 需要注意的是,由于只有Java进程才会向AMS注册,而一般的Native进程不会向AMS注册,因此此处杀死的进程是Java进程。
主要是调用一些关键服务的初始化函数,然后杀死那些没有FLAG_PERSISTENT 却在AMS启动完成前已经存在的进程,同时获取一些配置参数。需要注意的是,由于只有Java进程才会向AMS注册,而一般的Native进程不会向AMS注册,因此此处杀手的进程是Java进程。
执行goingCallback的处理,主要的工作就是通知一些服务可以进行systemReady相关的工作,并进行启动服务或应用进程的工作
监控Native的crash,启动WebView,执行一些服务的systemReady和systemRunning方法
启动Home Activity,当启动结束,发送ACTION_BOOT_COMPLETED广播时,AMS的启动过程告一段落
启动Home Activity
AMS的启动主要经历了如下几个阶段:
WMS 启动流程
WMS作为系统的一个关键服务其是在SystemServer.java::startOtherServices中启动的
WMS主要有下面几个作用:
1:应用程序通过WMS向SurfaceFinger申请surface,surface代表的是绘图表面,应用程序绘制都必须在绘图表面上.
2:管理窗口的层级,一个窗口一般在WMS端都是一个WindowState,其是有层级区分的,其有baseLayer和subLayer两个值共同确定.
3:窗口动画:WindowAnimator
其中上面有一个比较重要的对象PhoneWindowManager,主要是负责窗口管理的各种策略
AMS,WMS之间数据是对应的,通过token值可以在AMS,WMS,应用程序之后来唯一确定一组Window,token是关联着一组窗口的,可能有多个WindowState的token值是相同的.
整个启动过程涉及3个线程: system_server主线程, “android.display”, “android.ui”, 整个过程是采用阻塞方式(利用Handler.runWithScissors)执行的. 其中WindowManagerService.mH的Looper运行在 “android.display”进程,也就意味着WMS.H.handleMessage()在该线程执行。
Android系统启动-SystemServer进程
相关源码文件:
根据上篇 Android系统启动-Zygote进程
文章,在Zygote进程启动时,会调用 ZygoteInit.main() 方法,其中分别会调用 registerZygoteSocket、preload 、startSystemServer 、runSelectLoop 来创建服务Socket、提前加载资源、创建SystemServer进程、循环创建子进程。
本篇文章讲解 startSystemServer() 方法,在startSystemServer()方法中主要完成两件事:
· 创建SystemServer进程
· SystemServer进程启动系统服务
下图则是startSystemServer方法的创建过程,先通过 Zygote.forkSystemServe 去创建SystemServer进程,创建SystemServer进程之后,通过 handleSystemServerProcess() 在SystemServer进程中去启动服务。
Zygote.forkSystemServer :
创建 SystemServer 进程是通过 com.android.internal.os. Zygote 的 nativeForkSystemServer 本地方法创建的,JNI方法的注册在 AndroidRuntime 中,通过查询可以知道对应的方法为:com_android_internal_os_Zygote.cpp类的com_android_internal_os_Zygote_nativeForkAndSpecialize()方法。最后通过 ForkAndSpecializeCommon 方法 fork() 创建SystemServer进程。
handleSystemServerProcess(parsedArgs)
通过一连串的分析得知,一是通过 nativeZygoteInit 去启动Bind,二是通过 applicationInit 方法通过异常去反射执行 SystemServer.main 方法,这里为什么需要通过异常去反射执行方法呢?为什么不直接反射执行方法?其实是为了清空栈的信息。到这里并没有启动服务,接下来的 SystemServer.main 方法是启动服务的开始。
SystemServer.main
SystemServer执行 main() 方法后调用 run 方法,之后分别调用 startBootstrapServices 、 startCoreServices 、 startOtherServices 开始启动很多服务,像常见的 ActivityManagerService、PackageManagerService、WindowManagerService、InputManagerServic 服务都在这里开启。
开启服务有两种方式:
但是发现最终都是调用到LocalServices.addService这种方法。
可见启动服务是靠Binder驱动去开启的。
首先通过JNI的注册方法去创建SystemServer进程,创建进程之后,开始处理SystemServer进程,通过异常反射调用SystemServer的main方法,主要完成两件事:一、启动Binder驱动线程,二、开启服务(AMS、PMS、WMS、IMS等),最后通过Binder驱动去启动服务。
Android输入法IMMS服务启动流程(3)(启动IMS应用)
接上一篇,IMMS设置当前默认输入法为LatinIME输入法后,调用onCreate方法,然后会调用startInputInnerLocked启动输入法LatinIME的服务
本章节主要分析,onCreate生命周期中,各个流程调用
bindServiceAsUser启动的服务是LatinIME
如上图流程图,服务启动后,会调用到InputMethodManagerService的setAdditionalInputMethodSubtypes方法
该流程的主要逻辑:
完成对mMethodList和mMethodMap的数据初始化;检查当前默认的输入法(LatinIME)服务是否存在,很明显,经过systemrunning过程以后,
mMethodMap已经包含了LatinIME,因此不会重复执行选择和设定另外输入法为默认输入法的操作
该方法主要是检查默认的LatinIME是否是可用的可用的输入法,如果不可用,则设置为可用;
对应的settingprovider字段为:
经过以上流程后,默认输入法依然为LatinIME输入法,该流程的主要作用为,将启动的输入法应用更新到可用列表enabled_input_methods中;
不过,目前默认的输入法依然为LatinIME输入法,跟重启手机前,我们设置的输入法(搜狗输入法)依然不一致
下一篇文章,我们研究下,输入法启动过程中的onBind和onServiceConnected流程

更多文章:
gridview控件的常用自定义列有哪些?分别有什么作用?(.net有关的基础问题)
2026年10月11日 23:50
在from子句中可以出现(如何在from 子句中嵌套查询下面的语句在access中出错!)
2026年10月11日 05:20
countif函数统计个数怎么用(countif函数怎么用 详解Excel中countif函数的使用方法)
2026年10月11日 03:30






