android服务的启动过程,Android Service的启动过程(上)

原标题:Android Service的启动过程(上)

(点击上方公众号,可快速关注)

来源:伯乐在线专栏作者 - xuyinhuan

链接:http://android.jobbole.com/85150/

刚开始学习Service的时候以为它是一个线程的封装,也可以执行耗时操作。其实不然,Service是运行在主线程的。直接执行耗时操作是会阻塞主线程的。长时间就直接ANR了。

我们知道Service可以执行一些后台任务,是后台任务不是耗时的任务,后台和耗时是有区别的喔。

这样就很容易想到音乐播放器,天气预报这些应用是要用到Service的。当然如果要在Service中执行耗时操作的话,开个线程就可以了。

关于Service的运行状态有两种,启动状态和绑定状态,两种状态可以一起。

启动一个Service只需调用Context的startService方法,传进一个Intent即可。看起来好像很简单的说,那是因为Android为了方便开发者,做了很大程度的封装。那么你真的有去学习过Service是怎么启动的吗?Service的onCreate方法回调前都做了哪些准备工作?

先上一张图大致了解下,灰色背景框起来的是同一个类中的方法,如下图:

253f2124a1fe5d4d1e19a6d701a341df.png

那接下来就从源码的角度来分析Service的启动过程。

当然是从Context的startService方法开始,Context的实现类是ContextImpl,那么我们就看到ContextImpl的startService方法即可,如下:

@Override

publicComponentName startService(Intentservice){

warnIfCallingFromSystemProcess();

returnstartServiceCommon(service,mUser);

}

会转到startServiceCommon方法,那跟进startServiceCommon方法方法瞧瞧。

privateComponentName startServiceCommon(Intentservice,UserHandleuser){

try{

validateServiceIntent(service);

service.prepareToLeaveProcess();

ComponentNamecn=ActivityManagerNative.getDefault().startService(

mMainThread.getApplicationThread(),service,service.resolveTypeIfNeeded(

getContentResolver()),getOpPackageName(),user.getIdentifier());

//代码省略

returncn;

}catch(RemoteExceptione){

thrownewRuntimeException("Failure from system",e);

}

}

可以看到调用了ActivityManagerNative.getDefault()的startService方法来启动Service,ActivityManagerNative.getDefault()是ActivityManagerService,简称AMS。

那么现在启动Service的过程就转移到了ActivityManagerService,我们关注ActivityManagerService的startService方法即可,如下:

@Override

publicComponentName startService(IApplicationThreadcaller,Intentservice,

StringresolvedType,StringcallingPackage,intuserId)

throwsTransactionTooLargeException{

//代码省略

synchronized(this){

finalintcallingPid=Binder.getCallingPid();

finalintcallingUid=Binder.getCallingUid();

finallongorigId=Binder.clearCallingIdentity();

ComponentNameres=mServices.startServiceLocked(caller,service,

resolvedType,callingPid,callingUid,callingPackage,userId);

Binder.restoreCallingIdentity(origId);

returnres;

}

}

在上述的代码中,调用了ActiveServices的startServiceLocked方法,那么现在Service的启动过程从AMS转移到了ActiveServices了。

继续跟进ActiveServices的startServiceLocked方法,如下:

ComponentName startServiceLocked(IApplicationThreadcaller,Intentservice,StringresolvedType,

intcallingPid,intcallingUid,StringcallingPackage,intuserId)

throwsTransactionTooLargeException{

//代码省略

ServiceLookupResultres=

retrieveServiceLocked(service,resolvedType,callingPackage,

callingPid,callingUid,userId,true,callerFg);

//代码省略

ServiceRecordr=res.record;

//代码省略

returnstartServiceInnerLocked(smap,service,r,callerFg,addToStarting);

}

在startServiceLocked方法中又会调用startServiceInnerLocked方法,

我们瞧瞧startServiceInnerLocked方法,

ComponentName startServiceInnerLocked(ServiceMapsmap,Intentservice,ServiceRecordr,

booleancallerFg,booleanaddToStarting)throwsTransactionTooLargeException{

ProcessStats.ServiceStatestracker=r.getTracker();

if(stracker!=null){

stracker.setStarted(true,mAm.mProcessStats.getMemFactorLocked(),r.lastActivity);

}

r.callStart=false;

synchronized(r.stats.getBatteryStats()){

r.stats.startRunningLocked();

}

Stringerror=bringUpServiceLocked(r,service.getFlags(),callerFg,false);

//代码省略

returnr.name;

}

startServiceInnerLocked方法内部调用了bringUpServiceLocked方法,此时启动过程已经快要离开ActiveServices了。继续看到bringUpServiceLocked方法。如下:

privatefinalStringbringUpServiceLocked(ServiceRecordr,intintentFlags,booleanexecInFg,

booleanwhileRestarting)throwsTransactionTooLargeException{

//代码省略

if(app!=null&&app.thread!=null){

try{

app.addPackage(r.appInfo.packageName,r.appInfo.versionCode,mAm.mProcessStats);

realStartServiceLocked(r,app,execInFg);

returnnull;

}

//代码省略

returnnull;

}

省略了大部分if判断,相信眼尖的你一定发现了核心的方法,那就是

realStartServiceLocked,没错,看名字就像是真正启动Service。那么事不宜迟跟进去探探吧。如下:

privatefinalvoidrealStartServiceLocked(ServiceRecordr,

ProcessRecordapp,booleanexecInFg)throwsRemoteException{

//代码省略

booleancreated=false;

try{

//代码省略

app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);

app.thread.scheduleCreateService(r,r.serviceInfo,

mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),

app.repProcState);

r.postNotification();

created=true;

}catch(DeadObjectExceptione){

Slog.w(TAG,"Application dead when creating service "+r);

mAm.appDiedLocked(app);

throwe;

}

//代码省略

sendServiceArgsLocked(r,execInFg,true);

//代码省略

}

找到了。app.thread调用了scheduleCreateService来启动Service,而app.thread是一个ApplicationThread,也是ActivityThread的内部类。此时已经到了主线程。

那么我们探探ApplicationThread的scheduleCreateService方法。如下:

publicfinalvoidscheduleCreateService(IBindertoken,

ServiceInfoinfo,CompatibilityInfocompatInfo,intprocessState){

updateProcessState(processState,false);

CreateServiceDatas=newCreateServiceData();

s.token=token;

s.info=info;

s.compatInfo=compatInfo;

sendMessage(H.CREATE_SERVICE,s);

}

对待启动的Service组件信息进行包装,然后发送了一个消息。我们关注这个CREATE_SERVICE消息即可。

publicvoidhandleMessage(Messagemsg){

//代码省略

caseCREATE_SERVICE:

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"serviceCreate");

handleCreateService((CreateServiceData)msg.obj);

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

break;

//代码省略

}

在handleMessage方法中接收到这个消息,然后调用了handleCreateService方法,跟进handleCreateService探探究竟:

privatevoidhandleCreateService(CreateServiceDatadata){

// If we are getting ready to gc after going to the background, well

// we are back active so skip it.

unscheduleGcIdler();

LoadedApkpackageInfo=getPackageInfoNoCheck(

data.info.applicationInfo,data.compatInfo);

Serviceservice=null;

try{

java.lang.ClassLoadercl=packageInfo.getClassLoader();

service=(Service)cl.loadClass(data.info.name).newInstance();

}catch(Exceptione){

if(!mInstrumentation.onException(service,e)){

thrownewRuntimeException(

"Unable to instantiate service "+data.info.name

+": "+e.toString(),e);

}

}

try{

if(localLOGV)Slog.v(TAG,"Creating service "+data.info.name);

ContextImplcontext=ContextImpl.createAppContext(this,packageInfo);

context.setOuterContext(service);

Applicationapp=packageInfo.makeApplication(false,mInstrumentation);

service.attach(context,this,data.info.name,data.token,app,

ActivityManagerNative.getDefault());

service.onCreate();

mServices.put(data.token,service);

try{

ActivityManagerNative.getDefault().serviceDoneExecuting(

data.token,SERVICE_DONE_EXECUTING_ANON,0,0);

}catch(RemoteExceptione){

// nothing to do.

}

}catch(Exceptione){

if(!mInstrumentation.onException(service,e)){

thrownewRuntimeException(

"Unable to create service "+data.info.name

+": "+e.toString(),e);

}

}

}

终于击破,这个方法很核心的。一点点分析

接下文

关注「安卓开发精选」

看更多精选安卓技术文章

责任编辑:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值