Android Service的启动过程.docx

上传人:b****2 文档编号:3159361 上传时间:2023-05-05 格式:DOCX 页数:15 大小:59.07KB
下载 相关 举报
Android Service的启动过程.docx_第1页
第1页 / 共15页
Android Service的启动过程.docx_第2页
第2页 / 共15页
Android Service的启动过程.docx_第3页
第3页 / 共15页
Android Service的启动过程.docx_第4页
第4页 / 共15页
Android Service的启动过程.docx_第5页
第5页 / 共15页
Android Service的启动过程.docx_第6页
第6页 / 共15页
Android Service的启动过程.docx_第7页
第7页 / 共15页
Android Service的启动过程.docx_第8页
第8页 / 共15页
Android Service的启动过程.docx_第9页
第9页 / 共15页
Android Service的启动过程.docx_第10页
第10页 / 共15页
Android Service的启动过程.docx_第11页
第11页 / 共15页
Android Service的启动过程.docx_第12页
第12页 / 共15页
Android Service的启动过程.docx_第13页
第13页 / 共15页
Android Service的启动过程.docx_第14页
第14页 / 共15页
Android Service的启动过程.docx_第15页
第15页 / 共15页
亲,该文档总共15页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

Android Service的启动过程.docx

《Android Service的启动过程.docx》由会员分享,可在线阅读,更多相关《Android Service的启动过程.docx(15页珍藏版)》请在冰点文库上搜索。

Android Service的启动过程.docx

AndroidService的启动过程

AndroidService的启动过程

刚开始学习Service的时候以为它是一个线程的封装,也可以执行耗时操作。

其实不然,Service是运行在主线程的。

直接执行耗时操作是会阻塞主线程的。

长时间就直接ANR了。

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

这样就很容易想到音乐播放器,天气预报这些应用是要用到Service的。

当然如果要在Service中执行耗时操作的话,开个线程就可以了。

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

启动一个Service只需调用Context的startService方法,传进一个Intent即可。

看起来好像很简单的说,那是因为Android为了方便开发者,做了很大程度的封装。

那么你真的有去学习过Service是怎么启动的吗?

Service的onCreate方法回调前都做了哪些准备工作?

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

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

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

@Override

publicComponentNamestartService(Intentservice){

warnIfCallingFromSystemProcess();

returnstartServiceCommon(service,mUser);

}

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

privateComponentNamestartServiceCommon(Intentservice,UserHandleuser){

try{

validateServiceIntent(service);

service.prepareToLeaveProcess();

ComponentNamecn=ActivityManagerNative.getDefault().startService(

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

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

//代码省略

returncn;

}catch(RemoteExceptione){

thrownewRuntimeException("Failurefromsystem",e);

}

}

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

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

@Override

publicComponentNamestartService(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方法,如下:

ComponentNamestartServiceLocked(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方法,

ComponentNamestartServiceInnerLocked(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,

mApatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),

app.repProcState);

r.postNotification();

created=true;

}catch(DeadObjectExceptione){

Slog.w(TAG,"Applicationdeadwhencreatingservice"+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;

patInfo=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){

//Ifwearegettingreadytogcaftergoingtothebackground,well

//wearebackactivesoskipit.

unscheduleGcIdler();

LoadedApkpackageInfo=getPackageInfoNoCheck(

data.info.applicationInfo,patInfo);

Serviceservice=null;

try{

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

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

}catch(Exceptione){

if(!

mInstrumentation.onException(service,e)){

thrownewRuntimeException(

"Unabletoinstantiateservice"+data.info.name

+":

"+e.toString(),e);

}

}

try{

if(localLOGV)Slog.v(TAG,"Creatingservice"+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){

//nothingtodo.

}

}catch(Exceptione){

if(!

mInstrumentation.onException(service,e)){

thrownewRuntimeException(

"Unabletocreateservice"+data.info.name

+":

"+e.toString(),e);

}

}

}

终于击破,这个方法很核心的。

一点点分析

首先获取到一个LoadedApk对象,在通过这个LoadedApk对象获取到一个类加载器,通过这个类加载器来创建Service。

如下:

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

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

接着调用ContextImpl的createAppContext方法创建了一个ContextImpl对象。

之后再调用LoadedApk的makeApplication方法来创建Application,这个创建过程如下:

publicApplicationmakeApplication(booleanforceDefaultAppClass,

Instrumentationinstrumentation){

if(mApplication!

=null){

returnmApplication;

}

Applicationapp=null;

StringappClass=mApplicationInfo.className;

if(forceDefaultAppClass||(appClass==null)){

appClass="android.app.Application";

}

try{

java.lang.ClassLoadercl=getClassLoader();

if(!

mPackageName.equals("android")){

initializeJavaContextClassLoader();

}

ContextImplappContext=ContextImpl.createAppContext(mActivityThread,this);

app=mActivityThread.mInstrumentation.newApplication(

cl,appClass,appContext);

appContext.setOuterContext(app);

}catch(Exceptione){

if(!

mActivityThread.mInstrumentation.onException(app,e)){

thrownewRuntimeException(

"Unabletoinstantiateapplication"+appClass

+":

"+e.toString(),e);

}

}

mActivityThread.mAllApplications.add(app);

mApplication=app;

if(instrumentation!

=null){

try{

instrumentation.callApplicationOnCreate(app);

}catch(Exceptione){

if(!

instrumentation.onException(app,e)){

thrownewRuntimeException(

"Unabletocreateapplication"+app.getClass().getName()

+":

"+e.toString(),e);

}

}

}

//RewritetheR'constants'foralllibraryapks.

SparseArraypackageIdentifiers=getAssets(mActivityThread)

.getAssignedPackageIdentifiers();

finalintN=packageIdentifiers.size();

for(inti=0;i

finalintid=packageIdentifiers.keyAt(i);

if(id==0x01||id==0x7f){

continue;

}

rewriteRValues(getClassLoader(),packageIdentifiers.valueAt(i),id);

}

returnapp;

}

当然Application是只有一个的,从上述代码中也可以看出。

在回来继续看handleCreateService方法,之后service调用了attach方法关联了ContextImpl和Application等

最后service回调了onCreate方法,

service.onCreate();

mServices.put(data.token,service);

并将这个service添加进了一个了列表进行管理。

至此service启动了起来,以上就是service的启动过程。

你可能还想要知道onStartCommand方法是怎么被回调的?

可能细心的你发现了在ActiveServices的realStartServiceLocked方法中,那里还有一个sendServiceArgsLocked方法。

是的,那个就是入口。

那么我们跟进sendServiceArgsLocked方法看看onStartCommand方法是怎么回调的。

privatefinalvoidsendServiceArgsLocked(ServiceRecordr,booleanexecInFg,

booleanoomAdjusted)throwsTransactionTooLargeException{

finalintN=r.pendingStarts.size();

//代码省略

try{

//代码省略

r.app.thread.scheduleServiceArgs(r,si.taskRemoved,si.id,flags,si.intent);

}ch(TransactionTooLargeExceptione){

if(DEBUG_SERVICE)Slog.v(TAG_SERVICE,"Transactiontoolarge:

intent="

+si.intent);

caughtException=e;

}catch(RemoteExceptione){

//Remoteprocessgone...we'llletthenormalcleanuptakecareofthis.

if(DEBUG_SERVICE)Slog.v(TAG_SERVICE,"Crashedwhilesendingargs:

"+r);

caughtException=e;

}

//代

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2