Android Service的启动过程.docx
《Android Service的启动过程.docx》由会员分享,可在线阅读,更多相关《Android Service的启动过程.docx(15页珍藏版)》请在冰点文库上搜索。
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;ifinalintid=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;
}
//代