原标题:Android Service的启动过程(上)
(点击上方公众号,可快速关注)
来源:伯乐在线专栏作者 - xuyinhuan
链接:http://android.jobbole.com/85150/
刚开始学习Service的时候以为它是一个线程的封装,也可以执行耗时操作。其实不然,Service是运行在主线程的。直接执行耗时操作是会阻塞主线程的。长时间就直接ANR了。
我们知道Service可以执行一些后台任务,是后台任务不是耗时的任务,后台和耗时是有区别的喔。
这样就很容易想到音乐播放器,天气预报这些应用是要用到Service的。当然如果要在Service中执行耗时操作的话,开个线程就可以了。
关于Service的运行状态有两种,启动状态和绑定状态,两种状态可以一起。
启动一个Service只需调用Context的startService方法,传进一个Intent即可。看起来好像很简单的说,那是因为Android为了方便开发者,做了很大程度的封装。那么你真的有去学习过Service是怎么启动的吗?Service的onCreate方法回调前都做了哪些准备工作?
先上一张图大致了解下,灰色背景框起来的是同一个类中的方法,如下图:
那接下来就从源码的角度来分析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);
}
}
}
终于击破,这个方法很核心的。一点点分析
接下文
关注「安卓开发精选」
看更多精选安卓技术文章
责任编辑: