service启动activity_「 Android 10 四大组件 」系列—Service 的 quot; 启动流程 quot;
核心源碼
關(guān)鍵類路徑
Service 的啟動過程相對 Activity 的啟動過程來說簡單了很多,我們都知道怎么去創(chuàng)建和啟動一個 Service, 那么你有沒有從源碼角度研究過 Service 啟動后在系統(tǒng)層是如何運作的 ?
第一次看我文章的小伙伴可以關(guān)注一下我,順便關(guān)注一下我的專欄:Android高級開發(fā)架構(gòu)技術(shù)專欄,每天更新各種技術(shù)干貨,分享更多最熱程序員圈內(nèi)事。Android高級開發(fā)架構(gòu)技術(shù)專欄?zhuanlan.zhihu.comActivity.startService()
首先我們知道:要啟動一個 Service 的時候,一般都是在 Activity 中通過 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;}};}但是我們在 Activity 源碼中并沒有實現(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 中實現(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() 方法其實是由 ContextWrapper 實現(xiàn)的,緊接著又調(diào)用了 mBase.startService() 方法, mBase 對象是 Context 的子類 ContextImpl ,所以調(diào)用最終進入 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()
接下來就執(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;}}通過 retrieveServiceLocked() 方法來解析 AndroidManifest.xml 文件中配置 Service 的 intent-filter 相關(guān)內(nèi)容信息。
當解析完 Service 的 intent-filter 相關(guān)內(nèi)容信息后,解析的結(jié)果會保存在 res.record 變量中。而 res 變量是一個 ServiceLookupResult 類型的對象,它的 record 變量則是一個 ServiceRecord 類型對象,用來表示一個 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() 方法進一步處理:
// 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() 方法首先通過 getProcessRecordLocked() 方法去獲取 app 對象,它是一個 ProcessRecord 類型的對象,如果它不為空,說明 Service 要運行的進程已經(jīng)存在。
Service 運行的進程有兩種:
(1)一種是默認的,即運行在 Activity 啟動 Service 的那個進程里,也就是說在哪個進程里調(diào)用了 startService() 方法,啟動的 service 就運行在哪個進程里。
(2)一種是給 Service 一個單獨的進程運行,比如在 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" 聲明,這個聲明用來實現(xiàn) service 單獨運行在 "xxx" 進程里。這樣做的好處是, 即使應用程序無法工作,由于 service 單獨運行在一個進程里,所以會繼續(xù)工作 。
回到前面的方法,如果變量 app 為空,就代表 service 要運行的進程還沒有啟動,于是調(diào)用 startProcessLocked() 方法去啟動一個新的進程。
如果 app 不為空,采用默認的方式啟動 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());... ...}... ...}}在這個方法中,app 對象的 thread 變量是一個 ApplicationThread Binder 對象,調(diào)用它的scheduleCreateService() 方法之后,會進入客戶端的 ActivityThread 中。
ActivityThread.scheduleCreateService()
// frameworks/base/core/java/android/app/ActivityThread.javapublic final class ActivityThread extends ClientTransactionHandler {// ApplicationThread 是一個 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() 方法通過調(diào)用 sendMessage() 方法來發(fā)送一個 msg 消息 ,當 Handler 接收到了 msg 消息之后,它會調(diào)用 handleCreateService() 方法來做進一步處理。
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(); // 進入 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() 方法中,首先通過 ClassLoader 類把 Service 加載進來,而參數(shù) data.info.name 表示這個 Service 的名字, instantiateService() 方法是創(chuàng)建一個 Service 實例。接著, 創(chuàng)建一個 Context 對象 ,作為上下文環(huán)境之用。
handleCreateService() 方法最后調(diào)用了 service 的 onCreate() 方法 ,當這個方法被調(diào)用之后, 就會進入應用程序里 Service 的 onCreate() 方法 。
至此,Service 的啟動就分析完畢,這個過程與啟動 Activity 相比簡單了很多。
總結(jié)
看到最后,希望這篇文章能幫你梳理清楚 “Service 的啟動流程” 。
我整理了一些Activity的資料,如果你有需要可以私信我獲取
還有Android學習PDF+架構(gòu)視頻+面試文檔+源碼筆記,高級架構(gòu)技術(shù)進階腦圖、Android開發(fā)面試專題資料,高級進階架構(gòu)資料這些都是我閑暇還會反復翻閱的精品資料
總之也是在這里幫助大家學習提升進階,也節(jié)省大家在網(wǎng)上搜索資料的時間來學習,也可以分享給身邊好友一起學習
如果你有需要的話,可以點贊+評論,關(guān)注我,然后私信我【學習】獲取
總結(jié)
以上是生活随笔為你收集整理的service启动activity_「 Android 10 四大组件 」系列—Service 的 quot; 启动流程 quot;的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 水晶报表 jar包版本过低_工具类学习-
- 下一篇: 分段线性插值c语言程序_【短道速滑】Op