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方法回調前都做了哪些準備工作?
先上一張圖大致了解下,灰色背景框起來的是同一個類中的方法,如下圖:
那接下來就從源碼的角度來分析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);
}
}
}
終于擊破,這個方法很核心的。一點點分析
接下文
關注「安卓開發精選」
看更多精選安卓技術文章
責任編輯:
總結
以上是生活随笔為你收集整理的android服务的启动过程,Android Service的启动过程(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言农夫过河游戏代码解释,农夫过河C+
- 下一篇: android 手动 打包,androi