service启动activity_「 Android 10 四大组件 」系列—Service 的 quot; 启动流程 quot;
核心源碼
關(guān)鍵類路徑
Service 的啟動(dòng)過(guò)程相對(duì) Activity 的啟動(dòng)過(guò)程來(lái)說(shuō)簡(jiǎn)單了很多,我們都知道怎么去創(chuàng)建和啟動(dòng)一個(gè) Service, 那么你有沒(méi)有從源碼角度研究過(guò) Service 啟動(dòng)后在系統(tǒng)層是如何運(yùn)作的 ?
第一次看我文章的小伙伴可以關(guān)注一下我,順便關(guān)注一下我的專欄:Android高級(jí)開(kāi)發(fā)架構(gòu)技術(shù)專欄,每天更新各種技術(shù)干貨,分享更多最熱程序員圈內(nèi)事。Android高級(jí)開(kāi)發(fā)架構(gòu)技術(shù)專欄?zhuanlan.zhihu.comActivity.startService()
首先我們知道:要啟動(dòng)一個(gè) Service 的時(shí)候,一般都是在 Activity 中通過(guò) startService() 來(lái)啟動(dòng):
// frameworks/base/core/java/android/app/ActivityManager.javapublic class ActivityManager {@UnsupportedAppUsagepublic static IActivityManager getService() {return IActivityManagerSingleton.get();}@UnsupportedAppUsageprivate static final Singleton<IActivityManager> IActivityManagerSingleton =new Singleton<IActivityManager>() {@Overrideprotected IActivityManager create() {final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);final IActivityManager am = IActivityManager.Stub.asInterface(b);return am;}};}但是我們?cè)?Activity 源碼中并沒(méi)有實(shí)現(xiàn) startService() 方法,那它在哪里被調(diào)用的?找不到我們就去 Activity 的父類中找。
// frameworks/base/core/java/android/app/Activity.javapublic class Activity extends ContextThemeWrapperimplements LayoutInflater.Factory2,Window.Callback, KeyEvent.Callback,OnCreateContextMenuListener, ComponentCallbacks2,Window.OnWindowDismissedCallback, WindowControllerCallback,AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {}// frameworks/base/core/java/android/view/ContextThemeWrapper.javapublic class ContextThemeWrapper extends ContextWrapper {}// frameworks/base/core/java/android/content/ContextWrapper.java public class ContextWrapper extends Context {}Activity 繼承了 ContextThemeWrapper 類, ContextThemeWrapper 又繼承了 ContextWrapper類, ContextWrapper 又繼承了 Context 類。
ContextWrapper.startService()
在 ContextWrapper 中實(shí)現(xiàn)了 startService() 方法:
// frameworks/base/core/java/android/app/ActivityManager.javapublic class ActivityManager {@UnsupportedAppUsagepublic static IActivityManager getService() {return IActivityManagerSingleton.get();}@UnsupportedAppUsageprivate static final Singleton<IActivityManager> IActivityManagerSingleton =new Singleton<IActivityManager>() {@Overrideprotected IActivityManager create() {final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);final IActivityManager am = IActivityManager.Stub.asInterface(b);return am;}};}所以 startService() 方法其實(shí)是由 ContextWrapper 實(shí)現(xiàn)的,緊接著又調(diào)用了 mBase.startService() 方法, mBase 對(duì)象是 Context 的子類 ContextImpl ,所以調(diào)用最終進(jìn)入 ContextImpl類的 startService() 方法。
ContextImpl.startService()
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.javapublic final class ActiveServices {ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)throws TransactionTooLargeException {return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,callingPackage, userId, false);}ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,int callingPid, int callingUid, boolean fgRequired, String callingPackage,final int userId, boolean allowBackgroundActivityStarts)throws TransactionTooLargeException {... ...// 解析 AndroidManifest.xml 文件中配置 Service 的 intent-filter 相關(guān)內(nèi)容信息ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage,callingPid, callingUid, userId, true, callerFg, false, false);if (res == null) {return null;}... ...ServiceRecord r = res.record;... ...// 調(diào)用 startServiceInnerLocked() 方法ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);return cmp;}}ActivityManager.getService()
// frameworks/base/core/java/android/app/ActivityManager.javapublic class ActivityManager {@UnsupportedAppUsagepublic static IActivityManager getService() {return IActivityManagerSingleton.get();}@UnsupportedAppUsageprivate static final Singleton<IActivityManager> IActivityManagerSingleton =new Singleton<IActivityManager>() {@Overrideprotected IActivityManager create() {final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);final IActivityManager am = IActivityManager.Stub.asInterface(b);return am;}};}ActivityManagerService.startService()
接下來(lái)就執(zhí)行到 ActivityManagerService 的 startService() 方法:
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.javapublic final class ActiveServices {private final void realStartServiceLocked(ServiceRecord r,ProcessRecord app, boolean execInFg) throws RemoteException {... ...try {... ...app.thread.scheduleCreateService(r, r.serviceInfo,mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.getReportedProcState());... ...}... ...}}ActiveServices.startServiceLocked()
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.javapublic final class ActiveServices {ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)throws TransactionTooLargeException {return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired,callingPackage, userId, false);}ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,int callingPid, int callingUid, boolean fgRequired, String callingPackage,final int userId, boolean allowBackgroundActivityStarts)throws TransactionTooLargeException {... ...// 解析 AndroidManifest.xml 文件中配置 Service 的 intent-filter 相關(guān)內(nèi)容信息ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage,callingPid, callingUid, userId, true, callerFg, false, false);if (res == null) {return null;}... ...ServiceRecord r = res.record;... ...// 調(diào)用 startServiceInnerLocked() 方法ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);return cmp;}}通過(guò) retrieveServiceLocked() 方法來(lái)解析 AndroidManifest.xml 文件中配置 Service 的 intent-filter 相關(guān)內(nèi)容信息。
當(dāng)解析完 Service 的 intent-filter 相關(guān)內(nèi)容信息后,解析的結(jié)果會(huì)保存在 res.record 變量中。而 res 變量是一個(gè) ServiceLookupResult 類型的對(duì)象,它的 record 變量則是一個(gè) ServiceRecord 類型對(duì)象,用來(lái)表示一個(gè) Service 。
ActiveServices.startServiceInnerLocked()
ActiveServices 的 startServiceLocked() 方法最后調(diào)用了 startServiceInnerLocked() 方法:
//<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.android.documentsui"><applicationandroid:name=".DocumentsApplication"android:label="@string/app_label"android:icon="@drawable/app_icon"android:supportsRtl="true"android:allowBackup="true"android:backupAgent=".prefs.BackupAgent"android:fullBackupOnly="false"><!-- Run FileOperationService in a separate process so that we can use FileLock class towait until jumbo clip is done writing to disk before reading it. See ClipStorage fordetails. --><serviceandroid:name=".services.FileOperationService"android:exported="false"android:process=":com.android.documentsui.services"></service></application> </manifest>ActiveServices.bringUpServiceLocked()
調(diào)用 bringUpServiceLocked() 方法進(jìn)一步處理:
// frameworks/base/core/java/android/app/ActivityThread.javapublic final class ActivityThread extends ClientTransactionHandler {class H extends Handler {public void handleMessage(Message msg) {switch (msg.what) {case CREATE_SERVICE:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));handleCreateService((CreateServiceData)msg.obj); // 調(diào)用 handleCreateService() 方法Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;}}} }bringUpServiceLocked() 方法首先通過(guò) getProcessRecordLocked() 方法去獲取 app 對(duì)象,它是一個(gè) ProcessRecord 類型的對(duì)象,如果它不為空,說(shuō)明 Service 要運(yùn)行的進(jìn)程已經(jīng)存在。
Service 運(yùn)行的進(jìn)程有兩種:
(1)一種是默認(rèn)的,即運(yùn)行在 Activity 啟動(dòng) Service 的那個(gè)進(jìn)程里,也就是說(shuō)在哪個(gè)進(jìn)程里調(diào)用了 startService() 方法,啟動(dòng)的 service 就運(yùn)行在哪個(gè)進(jìn)程里。
(2)一種是給 Service 一個(gè)單獨(dú)的進(jìn)程運(yùn)行,比如在 AndroidManifest 文件里配置了如下內(nèi)容:
//<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.android.documentsui"><applicationandroid:name=".DocumentsApplication"android:label="@string/app_label"android:icon="@drawable/app_icon"android:supportsRtl="true"android:allowBackup="true"android:backupAgent=".prefs.BackupAgent"android:fullBackupOnly="false"><!-- Run FileOperationService in a separate process so that we can use FileLock class towait until jumbo clip is done writing to disk before reading it. See ClipStorage fordetails. --><serviceandroid:name=".services.FileOperationService"android:exported="false"android:process=":com.android.documentsui.services"></service></application> </manifest>在這段配置里有 android:process="xxx" 聲明,這個(gè)聲明用來(lái)實(shí)現(xiàn) service 單獨(dú)運(yùn)行在 "xxx" 進(jìn)程里。這樣做的好處是, 即使應(yīng)用程序無(wú)法工作,由于 service 單獨(dú)運(yùn)行在一個(gè)進(jìn)程里,所以會(huì)繼續(xù)工作 。
回到前面的方法,如果變量 app 為空,就代表 service 要運(yùn)行的進(jìn)程還沒(méi)有啟動(dòng),于是調(diào)用 startProcessLocked() 方法去啟動(dòng)一個(gè)新的進(jìn)程。
如果 app 不為空,采用默認(rèn)的方式啟動(dòng) Service,最終調(diào)用到 realStartServiceLocked() 方法:
ActiveServices.realStartServiceLocked()
// frameworks/base/services/core/java/com/android/server/am/ActiveServices.javapublic final class ActiveServices {private final void realStartServiceLocked(ServiceRecord r,ProcessRecord app, boolean execInFg) throws RemoteException {... ...try {... ...app.thread.scheduleCreateService(r, r.serviceInfo,mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.getReportedProcState());... ...}... ...}}在這個(gè)方法中,app 對(duì)象的 thread 變量是一個(gè) ApplicationThread Binder 對(duì)象,調(diào)用它的scheduleCreateService() 方法之后,會(huì)進(jìn)入客戶端的 ActivityThread 中。
ActivityThread.scheduleCreateService()
// frameworks/base/core/java/android/app/ActivityThread.javapublic final class ActivityThread extends ClientTransactionHandler {// ApplicationThread 是一個(gè) Binderprivate class ApplicationThread extends IApplicationThread.Stub {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);}}}ApplicationThread 的 scheduleCreateService() 方法通過(guò)調(diào)用 sendMessage() 方法來(lái)發(fā)送一個(gè) msg 消息 ,當(dāng) Handler 接收到了 msg 消息之后,它會(huì)調(diào)用 handleCreateService() 方法來(lái)做進(jìn)一步處理。
H.handleMessage()
// frameworks/base/core/java/android/app/ActivityThread.javapublic final class ActivityThread extends ClientTransactionHandler {class H extends Handler {public void handleMessage(Message msg) {switch (msg.what) {case CREATE_SERVICE:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));handleCreateService((CreateServiceData)msg.obj); // 調(diào)用 handleCreateService() 方法Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;}}} }ActivityThread.handleCreateService()
// frameworks/base/core/java/android/app/ActivityThread.javapublic final class ActivityThread extends ClientTransactionHandler {private void handleCreateService(CreateServiceData data) {... ...LoadedApk packageInfo = getPackageInfoNoCheck(data.info.applicationInfo, data.compatInfo);Service service = null;try {java.lang.ClassLoader cl = packageInfo.getClassLoader();service = packageInfo.getAppFactory().instantiateService(cl, data.info.name, data.intent);} catch (Exception e) {if (!mInstrumentation.onException(service, e)) {throw new RuntimeException("Unable to instantiate service " + data.info.name+ ": " + e.toString(), e);}}try {if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);ContextImpl context = ContextImpl.createAppContext(this, packageInfo);context.setOuterContext(service);Application app = packageInfo.makeApplication(false, mInstrumentation);service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService());service.onCreate(); // 進(jìn)入 Service.onCreate() 方法mServices.put(data.token, service);try {ActivityManager.getService().serviceDoneExecuting(data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}} catch (Exception e) {if (!mInstrumentation.onException(service, e)) {throw new RuntimeException("Unable to create service " + data.info.name+ ": " + e.toString(), e);}}}}在 ActivityThread 類的 handleCreateService() 方法中,首先通過(guò) ClassLoader 類把 Service 加載進(jìn)來(lái),而參數(shù) data.info.name 表示這個(gè) Service 的名字, instantiateService() 方法是創(chuàng)建一個(gè) Service 實(shí)例。接著, 創(chuàng)建一個(gè) Context 對(duì)象 ,作為上下文環(huán)境之用。
handleCreateService() 方法最后調(diào)用了 service 的 onCreate() 方法 ,當(dāng)這個(gè)方法被調(diào)用之后, 就會(huì)進(jìn)入應(yīng)用程序里 Service 的 onCreate() 方法 。
至此,Service 的啟動(dòng)就分析完畢,這個(gè)過(guò)程與啟動(dòng) Activity 相比簡(jiǎn)單了很多。
總結(jié)
看到最后,希望這篇文章能幫你梳理清楚 “Service 的啟動(dòng)流程” 。
我整理了一些Activity的資料,如果你有需要可以私信我獲取
還有Android學(xué)習(xí)PDF+架構(gòu)視頻+面試文檔+源碼筆記,高級(jí)架構(gòu)技術(shù)進(jìn)階腦圖、Android開(kāi)發(fā)面試專題資料,高級(jí)進(jìn)階架構(gòu)資料這些都是我閑暇還會(huì)反復(fù)翻閱的精品資料
總之也是在這里幫助大家學(xué)習(xí)提升進(jìn)階,也節(jié)省大家在網(wǎng)上搜索資料的時(shí)間來(lái)學(xué)習(xí),也可以分享給身邊好友一起學(xué)習(xí)
如果你有需要的話,可以點(diǎn)贊+評(píng)論,關(guān)注我,然后私信我【學(xué)習(xí)】獲取
總結(jié)
以上是生活随笔為你收集整理的service启动activity_「 Android 10 四大组件 」系列—Service 的 quot; 启动流程 quot;的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 水晶报表 jar包版本过低_工具类学习-
- 下一篇: Android标签库,JSP Strut