【Android话题-5.1应用相关】说说service的启动原理

【Android话题-5.1应用相关】说说service的启动原理,第1张

概述考察内容:service启动有哪几种方式?service启动过程中主要流程有哪些?service启动过程涉及哪些参与者,通信过程是怎样的?Service启动原理用startService启动Service:@OverridepublicComponentNamestartService(Intentservice){returnstartServiceCommon(service,

考察内容:

service启动有哪几种方式?service启动过程中主要流程有哪些?service启动过程涉及哪些参与者,通信过程是怎样的?Service启动原理用startService启动Service:
@OverrIDepublic Componentname startService(Intent service) {  return startServiceCommon(service, mUser);}Componentname startServiceCommon(Intent service, ...){  Componentname cn = ActivityManagerNative.getDefault()    .startService(mMainThread.getApplicationThread(), service, ...);  return cn;}

AMS中的处理:

Componentname startService(IApplicationThread caller, Intent service, ...){  Componentname res = mServices.startServiceLocked(caller, service, ...);  return res;}

根据intent 查询service Record对象:
每个应用端的Service在AMS中都对应一个ServiceRecore对象

Componentname startServiceLocked(Intent service, ...){  ServiceLookupResult res = retrIEveServiceLocked(service, ...);  ServiceRecord r = res.record;  ...  //查到ServiceRecord之后new了一个StartItem并加到pendingStart里面,  //为后面调用onStartCommand准备  r.pendingStart.add(new ServiceRecord.StartItem(r, ...));  ...  return startServiceInnerLocked(smap, service, r, ...);}Componentname startServiceInnerLocked(ServiceMap smap, Intent service, ...){  bringUpServiceLocked(r, service.getFlags(), callerFg, false);}final String bringUpServiceLocked(ServiceRecord r, ...){  if(r.app != null && r.app.thread != null) {    //如果Service已经启动了,就调用下面这个函数,    //它将触发应用端的onStartCommand    sendServiceArgsLocked(r, ...);    return null;  }  //Service还没启动的情况:  ProcessRecord app = mAm.getProcessRecordLocked(procname, ...);  if(app != null && app.thread != null){    //如果Service所在的进程已经启动了,真正启动Service    //r.app就是在下面这个函数中设置的    realStartServiceLocked(r, app, execInFg);    return null;  }  //Service所在进程没有启动或者虽然已经启动但还没就绪的情况:  if(app == null){    //app进程还没启动,启动进程    app = mAm.startProcessLocked(procname, ...);  }  if(!mPendingServices.contains(r)){    //把ServiceRecord加到pending列表里面,等待进程启动后再处理    mPendingServices.add(r);  }  ...}

进程启动的流程图:

AMS通过socket向Zygote发起启动进程的请求Zygote收到请求之后就会启动进程应用进程向AMS发起attachApplication的binder调用,把自己的binder对象注册到AMS(注册完之后对于AMS来说这个应用就算是就绪了)通过应用进程注册过来的applicationThread向应用端发起bindApplication调用,主应用初始化application(这步完事后AMS就可以处理Pending的组件了)AMS中处理attachApplication的函数:
boolean attachApplicationLocked(IApplicationThread thread, ...) {  ...  mServices.attachApplicationLocked(app, processname);  ...  return true;}//处理pending的Serviceboolean attachApplicationLocked(ProcessRecord proc, ...){  for(int i = 0; i < mPendingServices.size(); i++){    sr = mPendingServices.get(i);    ...    mPendingServices.remove(i--);    //对每一个pending的service调用realStartServiceLocked函数真正启动service    realStartServiceLocked(sr, proc, ...);  }  ...}voID realStartServiceLocked(ServiceRecord r, ProcessRecord app, ...){  r.app = app;  ...  //向应用端发起IPC调用,应用收到后就会创建Service,执行应用里的onCreate回调  //参数r其实是一个binder对象: final class ServiceRecord extends Binder{}  //这是要存在应用端的,应用端有一个用来保存service对象的map,这里的r就是key  app.thread.scheduleCreateService(r, r.serviceInfo, ...);  ...  //触发应用端Service的onStartCommand  sendServiceArgsLocked(r, ...);}
应用端是如何处理AMS发过来的CreateServicd请求的:
private voID handleCreateService(CreateServiceData data){  //先拿到loadedApk  LoadedApk packageInfo = getPackageInfoNoCheck(...);  //加载Service类,并通过newInstance调用其构造函数,从而获得Service对象  Service service = (Service)cl.loadClass(data.info.name).newInstance();  //给这个Service创建一个Context对象  ContextImpl context = ContextImpl.createAppContext(this, ...);  //获取Application,这个application是在应用启动的时候创建的  Application app = packageInfo.makeApplication(flase, ...);  //给service赋予上下文  service.attach(context, this, ...);  //执行Service的生命周期  service.onCreate();  mServices.put(data.token, service);  ...}mServices是一个map:ArrayMap<IBinder, Service>
private final voID sendServiceArgsLocked(ServiceRecord r, ){  while(r.pendingStarts.size() > 0){    //取出每一个pending的startItem    StartItem si = r.pendingStarts.remove(0);    ...    //向应用端发起IPC调用    r.app.thread.scheduleServiceArgs(r, ...);  }}
AMS是如何触发应用端Service的onStartCommand的

AMS调用r.app.thread.scheduleServiceArgs(r, …)后,应用端的处理:

public final voID scheduleServiceArgs(IBinder token, ...) {  //封装了一个ServiceArgsData对象  ServiceArgsData s = new ServiceArgsData();  ...  //丢到应用的主线程去处理  sendMessage(H.SERVICE_ARGS, s);}//应用端主线程的处理:private voID handleServiceArgs(ServiceArgsData data) {  //首先从mServices中把Service对象取出来。mService是一个map,其中:  //key就是AMS中的ServiceRecord的对象  //value就是应用端的Service对象  //data.token就是AMS中的ServiceRecord对象  Service s = mServices.get(data.token);  if(s != null){    ...    //调用Service的onStartCommand    s.onStartCommand(data.args, data.flags, data.startID);    ...  }}
总结Service启动的流程:


AMS端:

先看Service启动了没有:如果启动了就直接发指令,让应用端执行onStartCommand()如果Service没有启动,就看它所在进程启动了没有:如果已经启动,就去启动Service,等Service启动了之后再发送指令让其执行onStartCommand如果进程没有启动就去启动进程,等进程启动后再启动Service

应用端:

先创建Service对象再赋予上下文最后调用生命周期onCreate()用bindService启动Service

启动Service还有另一种情况:bindService的时候带上BIND_auto_CREATE标记

int bindServiceLocked(IApplicationThread caller, ...){  ...  if((flags & Context.BIND_auto_CREATE) != 0){    //如果带上BIND_auto_CREATE标记    bringUpServiceLocked(s, ...);  }  ...}
binderService和startService的区别:binderService不会触发应用端的onStartCommand函数因为binderService没有把ServiceRecord加到mPendingStart队列中回归:说说service的启动原理service启动有几种方式?
a) startService
b) bindService带BIND_auto_CREATEservice启动过程主要流程有哪些?
a)AMS端:
1)先看Service启动了没有:如果启动了就直接发指令,让应用端执行onStartCommand()
2)如果Service没有启动,就看它所在进程启动了没有:如果已经启动,就去启动Service,等Service启动了之后再发送指令让其执行onStartCommand
3)如果进程没有启动就去启动进程,等进程启动后再启动Service

b)应用端:
1)先创建Service对象
2)再赋予上下文
3)最后调用生命周期onCreate()

service启动过程中有哪些参与者,通信过程是怎样的?
a)参考下图:

点赞收藏分享文章举报

menghaocheng发布了119 篇原创文章 · 获赞 28 · 访问量 10万+私信 关注 总结

以上是内存溢出为你收集整理的【Android话题-5.1应用相关】说说service的启动原理全部内容,希望文章能够帮你解决【Android话题-5.1应用相关】说说service的启动原理所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/web/1066738.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存