先了解以下2篇,可以對Service的啟動過程有更好的理解
Android應用程序進程啟動過程
Binder深入理解及與AIDL的使用和理解
Service啟動過程
1. 先看一下startService()的使用示例
-
首先創建一個Service:
public class ClientService extends Service { //startService()方式啟動Service不會回調此方法 @Override public IBinder onBind(Intent intent) { return null; } //當Service被創建時調用 @Override public void onCreate() { super.onCreate(); } //當Service運行時調用 @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } //當Service被銷毀時調用 @Override public void onDestroy() { super.onDestroy(); } }
-
啟動Service:
Intent intent = new Intent(this, ClientService.class); startService(intent);
以上就是startService()方式啟動Service的示例
生命周期:onCreate()->onStartCommand()->onDestory()。多次調用startService()時onCreate()只會執行一次,但是onStartCommand()會多次執行。多次調用stopService(),onDestory()只會執行一次。
通過startService()方式啟動Service,只要不調用stopService(),就會一直運行,不會與調用者產生關聯。它的onBind()沒有返回Binder對象,所以調用者無法與Service產生交互。
2. Service的啟動過程:
startService()其實是由ContextImpl類型的mBase成員變量調用的,這個變量在ActivityThread的performLaunchActivity()中被創建,并通過attach()與Activity產生關聯。
startService()的啟動分為3個部分
ContextImpl到AMS到過程
AMS到ActivityThread過程
ActivityThread啟動Service過程
-
ContextImpl到AMS到過程:
那么看一下ContextImpl的startService():
@Override public boolean stopService(Intent service) { return stopServiceCommon(service, mUser); }
直接調用了stopServiceCommon():
private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) {\ //調用AMS的startService ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( getContentResolver()), requireForeground, getOpPackageName(), user.getIdentifier()); }
這里通過ActivityManager.getService()獲取了AMS,然后調用了它的startService(),而AMS是運行在SystemServer進程的,所以這里進程了進程間通訊。
總結:可以看到,ContextImpl到AMS到過程就是簡單的通知了AMS開始工作
-
AMS到ActivityThread過程:
這里繼續看AMS的startService():
public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, int userId){ //mServices是ActiveServices類型 res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, userId); return res; }
這里調用了ActiveServices的startServiceLocked(),看代碼:
ArrayMap<ComponentName, ServiceRecord> getServicesLocked(int callingUser) { return getServiceMapLocked(callingUser).mServicesByName; } //查找是否有與參數service對應的ServiceRecord,如果沒找到就會調用PackageManagerService去獲取參數service對應的Service信息,并封裝到ServiceRecord中。最后將ServiceRecord封裝為ServiceLookupResult返回,ServiceRecord用于描述一個Service ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg, false); //獲取ServiceRecord ServiceRecord r = res.record; //傳入ServiceRecord ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); return cmp; }
可以看到,這一步其實是獲取了ServiceRecord,它用來描述一個service,然后調用了startServiceInnerLocked(),看代碼:
ComponentName startServiceInnerLocked() { String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); return r.name; }
這里調用了bringUpServiceLocked(),繼續看代碼:
private String bringUpServiceLocked() { //獲取Service想要在哪個進程中運行,默認為當前進程 final String procName = r.processName; //ProcessRecord用來描述一個應用程序進程 ProcessRecord app; if (!isolated) { //mAm為AMS,通過AMS查詢是否存在一個與Service對應的ProcessRecord(進程)類型對象的app app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); //判斷用來運行Service的應用程序進程是否存在 if (app != null && app.thread != null) { //應用程序進程如果存在就啟動service realStartServiceLocked(r, app, execInFg); return null; } } if (app == null && !permissionsReviewRequired) { //用來運行Service的應用程序進程如果不存在就去啟動應用程序進程 if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, hostingType, r.name, false, isolated, false)) == null) { return msg; } } return null; }
可以看到這一步主要是判斷應用程序是否存在,如果不存在就去啟動應用程序進程。如果存在則繼續調用realStartServiceLocked(),并把進程信息ProcessRecord傳入,代碼:
private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { //這里這個app.thread指的是ActivityThread的內部類ApplicationThread。 app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo), app.repProcState); }
可以看到這里調用了app.thread.scheduleCreateService(),這里這個app.thread指的是ActivityThread的內部類ApplicationThread。這里進行了進程間通訊,切換到了應用程序進程。參考:Android中根Activity的啟動過程。
總結:可以看到,AMS到ActivityThread過程其實就是獲取要啟動的Service的信息,并判斷要啟動service的應用程序進程是否存在,如果不存在,就去啟動應用程序進程。如果存在,就進行進程間通訊,通知應用程序進程開始工作。
-
ActivityThread啟動Service過程:
public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) { updateProcessState(processState, false); CreateServiceData s = new CreateServiceData(); s.token = token; s.info = info; s.compatInfo = compatInfo; sendMessage(H.CREATE_SERVICE, s); }
再看這個sendMessage():
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) { Message msg = Message.obtain(); msg.what = what; msg.obj = obj; msg.arg1 = arg1; msg.arg2 = arg2; if (async) { msg.setAsynchronous(true); } //mH是H,繼承自Handler mH.sendMessage(msg); }
這里的mH是H,繼承自Handler。因為ApplicationThread負責進程間通訊,它運行在Binder線程池中,這里需要利用Handler切換到主線程。是Handler,那么就看它的handlerMessage():
public void handleMessage(Message msg) { switch (msg.what) { case CREATE_SERVICE: handleCreateService((CreateServiceData)msg.obj); break; }
調用了handleCreateService(),繼續看代碼:
private void handleCreateService(CreateServiceData data) { //獲取要啟動的Service的應用程序的LoadedApk,LoadedApk為APK文件的描述類 LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; //獲取類加載器 java.lang.ClassLoader cl = packageInfo.getClassLoader(); //使用類加載器創建service service = (Service) cl.loadClass(data.info.name).newInstance(); //創建service的上下文環境ContextImpl對象 ContextImpl context = ContextImpl.createAppContext(this, packageInfo); context.setOuterContext(service); Application app = packageInfo.makeApplication(false, mInstrumentation); //初始化Service service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); //調用onCreate() service.onCreate(); //將service添加到ActivityThread的ArrayMap類型的成員變量mServices中 mServices.put(data.token, service); }
這里可以看到,通過類加載器完成了service的創建,創建了context。然后通過attach()完成了service內部成員變量的初始化。最后調用了onCreate()。完成了startService()的啟動流程。
Service的綁定過程
1. 先看一下bindService()的使用示例:
-
首先創建一個Service
public class ClientService extends Service { private ServiceBinder serviceBinder; ////當Service綁定時調用,并返回binder對象 @Override public IBinder onBind(Intent intent) { return serviceBinder; } //當Service被創建時調用 @Override public void onCreate() { super.onCreate(); serviceBinder = new ServiceBinder(); } //當Service被解綁調用 @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } //當Service執行unbindService()解綁后,再次調用bindService()后調用 @Override public void onRebind(Intent intent) { super.onRebind(intent); } //當Service銷毀時調用 @Override public void onDestroy() { super.onDestroy(); } //Binder類 class ServiceBinder extends Binder { } }
-
創建一個Connection:
public class ClientConnection implements ServiceConnection { //當Service連接時調用,這里的ibinder就是Service里的onBinder()返回的binder @Override public void onServiceConnected(ComponentName name, IBinder ibinder) { } }
-
綁定service:
Intent intent = new Intent(this, ClientService.class); clientConnection = new ClientConnection(); bindService(intent, clientConnection, Context.BIND_AUTO_CREATE);
以上就是bindService()的示例。
生命周期:onCreate()->onBind()->onUnbind()->onDestory()
通過bindService()方式啟動Service會調用onCreate->onBinde(),多次調用bindService(),onCreate->onBinde()都只會執行一次,但是Connection的onServiceConnected()會執行多次。當執行unbindService()后再次bindService()則會執行onRebind()。
調用onBind()之后會在ClientConnection里返回onBinde()里的Binder對象,這個Binder對象是Service的成員變量,所以外界就可以訪問Service里。
通過bindService()方式啟動Service會與Activity產生關聯,所以必須在activity銷毀時執行onUnbind(),所以通過bindService()方式Service不能獨立運行。
2. Service的綁定過程
bindService()其實是由ContextImpl類型的mBase成員變量調用的,這個變量在ActivityThread的performLaunchActivity()中被創建,并通過attach()與Activity產生關聯。
bindService()的綁定過程分為3個部分:
ContextImpl到AMS到過程
Service的綁定過程
-
ContextImpl到AMS到過程:
那么看一下ContextImpl的bindService():
@Override public boolean bindService(Intent service, ServiceConnection conn, int flags) { //調用bindServiceCommon(),并傳入了ServiceConnection return bindServiceCommon(service, conn, flags, mMainThread.getHandler(), Process.myUserHandle()); }
可以看到,這里調用了bindServiceCommon(),繼續看:
private boolean bindServiceCommon() { IServiceConnection sd; //這里的mPackageInfo是LoadAPK類型 sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); //獲取AMS,調用AMS的bindService(),并傳入了IServiceConnection,這個IServiceConnection是一個本地代理對象,具備進程間通訊能力 int res = ActivityManager.getService().bindService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, getOpPackageName(), user.getIdentifier()); }
這里先看一下LoadAPK的getServiceDispatcher():
public final IServiceConnection getServiceDispatcher() { LoadedApk.ServiceDispatcher sd = null; //sd是一個ServiceDispatcher對象 return sd.getIServiceConnection(); } }
繼續看getIServiceConnection():
ServiceDispatcher.InnerConnection mIServiceConnection; IServiceConnection getIServiceConnection() { return mIServiceConnection; } private static class InnerConnection extends IServiceConnection.Stub { }
可以看到,最終返回的是一個InnerConnection對象,它繼承自IServiceConnection.Stub,意味著實現Binder機制,讓Service具備了進程間通訊的能力。
-
Service的綁定過程:
這里繼續看AMS的bindService():
public int bindService() { synchronized(this) { //mServices是ActiveServices類型 return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, callingPackage, userId); } }
這里調用了ActiveServices.bindServiceLocked(),繼續看代碼:
int bindServiceLocked() { //獲取AppBindRecord AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp); //獲取ConnectionRecord ConnectionRecord c = new ConnectionRecord(b, activity, connection, flags, clientLabel, clientIntent); //啟動Service,這里啟動service和startService()里的啟動部分是一樣的,會調用到同一個方法 if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) { return 0; } if (s.app != null && b.intent.received) { //s.app != null表示Service已經運行,b.intent.received表示當前應用程序進程已經收到綁定Service時返回到Binder,如果是第一次調用那么onBind()還沒調用,所以這里暫時不會執行。在重新綁定時才會執行。 //這里的c.conn是InnerConnection,這里最終會執行onServiceConnected(),所以多次綁定會多次執行onServiceConnected(); c.conn.connected(s.name, b.intent.binder, false); if (b.intent.apps.size() == 1 && b.intent.doRebind) { //解綁后,再次綁定時。也就是執行了unbindService()后再次執行bindService() requestServiceBindingLocked(s, b.intent, callerFg, true); } } else if (!b.intent.requested) { //第一次綁定時,也就是執行bindService()時 requestServiceBindingLocked(s, b.intent, callerFg, false); } return 1; }
AppBindRecord:應用程序進程通過Intent綁定Service時,會通過AppBindRecord來維護Service與應用程序進程之間的關聯。其內部存儲了誰綁定的Service(ProcessRecord),被綁定的Service(AppBindRecord),綁定Service的Intent(IntentBindRecord)和所有綁定通信記錄的信息(ArraySet<ConnectionRecord>)。
ServiceRecord:用于描述一個Service
ConnectionRecord:用于描述應用程序進程和Service建立的一次通信
IntentBindRecord:用于描述綁定Service的Intent。
這里可以看到,先是獲取了Service的相關信息,然后啟動了Service。最后調用了requestServiceBindingLocked(s, b.intent, callerFg, false):
private final boolean requestServiceBindingLocked() { //r.app.thread是ActivityThread的內部類ApplicationThread類型 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState); return true; }
這里執行了BInder代理對象ActivityThread的scheduleBindService(),那么會切換到應用程序進程,執行ActivityThread的scheduleBindService(),看代碼:
public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) { BindServiceData s = new BindServiceData(); s.token = token; s.intent = intent; s.rebind = rebind; sendMessage(H.BIND_SERVICE, s); }
這里會繼續執行到H類的HandleMessage():
public void handleMessage(Message msg) { case BIND_SERVICE: handleBindService((BindServiceData)msg.obj); }
繼續看handleBindService():
private void handleBindService(BindServiceData data) { //取出Service Service s = mServices.get(data.token); try { if (!data.rebind) { //調用onBind() IBinder binder = s.onBind(data.intent); //調用AMS的publishService() ActivityManager.getService().publishService( data.token, data.intent, binder); } else { //調用Rebind() s.onRebind(data.intent); ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } } }
前面分析過,Service建立后會存在Service中,這里再取出來。然后調用onBind(),這時onBind()生命周期就被執行了。
這里不關注reBind()的情況。
然后這里又再次調用了AMS的publishService(),又進行了進程間通訊,又來到了AMS所在的SystemServer進程,看publishService()代碼:
public void publishService(IBinder token, Intent intent, IBinder service) { //mServices是ActiveServices類型 mServices.publishServiceLocked((ServiceRecord)token, intent, service); }
再看ActiveServices.publishServiceLocked():
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { //這里的c.conn是InnerConnection,InnerConnection c.conn.connected(r.name, service, false); }
可以看到,這里調用了InnerConnection類型的c.conn的connected(),在前面分析過InnerConnection是LoadApk內部類ServiceDispatcher的內部類,是一個Binder,這里是它的代理Binder對象。
那么這里就是通過代理Binder對象進行進程間通信,會執行應用程序端的InnerConnection的connected()。看代碼:
public void connected(ComponentName name, IBinder service, boolean dead) throws RemoteException { LoadedApk.ServiceDispatcher sd = mDispatcher.get(); if (sd != null) { sd.connected(name, service, dead); } }
可以看到執行了ServiceDispatcher的connected():
public void connected(ComponentName name, IBinder service, boolean dead) { if (mActivityThread != null) { //將消息發送到主線程 mActivityThread.post(new RunConnection(name, service, 0, dead)); } else { doConnected(name, service, dead); } }
現在還處于binder線程池中,所以要切換到主線程,RunConnection是一個Runnable,同時也是ServiceDispatcher的內部類,那么看它的run():
public void run() { if (mCommand == 0) { doConnected(mName, mService, mDead); } else if (mCommand == 1) { doDeath(mName, mService); } }
這里執行了ServiceDispatcher的doConnected():
public void doConnected(ComponentName name, IBinder service, boolean dead) { //執行自定義的Connection的onServiceConnected() mConnection.onServiceConnected(name, service); }
到這時,就會執行自定義的Connection的onServiceConnected(),完成整個bindService()流程。
附:
- startService()方式能長時間運行在主線程,但是Activity無法操作Service。bindService()方式可以讓調用端獲取binder對象,但是無法長期運行。所以可以結合使用。先startService()再bindService(),這樣使用時如果要銷毀Service的話必須stopService()和uBindService()一起使用(順序無所謂)。