作者:DeepCoder

核心源码

关键类路径

Service 的启动过程相对 Activity 的启动过程来说简单了很多,我们都知道怎么去创建和启动一个 Service, 那么你有没有从源码角度研究过 Service 启动后在系统层是如何运作的 ?

第一次看我文章的小伙伴可以关注一下我,顺便关注一下我的专栏:Android高级开发架构技术专栏,每天更新各种技术干货,分享更多最热程序员圈内事。

Android高级开发架构技术专栏​zhuanlan.zhihu.com

Activity.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 源码中并没有实现 startService() 方法,那它在哪里被调用的?找不到我们就去 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 中实现了 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 实现的,紧接着又调用了 mBase.startService() 方法, mBase 对象是 Context 的子类 ContextImpl ,所以调用最终进入 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 相关内容信息ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage,callingPid, callingUid, userId, true, callerFg, false, false);if (res == null) {return null;}... ...ServiceRecord r = res.record;... ...// 调用 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()

接下来就执行到 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 相关内容信息ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage,callingPid, callingUid, userId, true, callerFg, false, false);if (res == null) {return null;}... ...ServiceRecord r = res.record;... ...// 调用 startServiceInnerLocked() 方法ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);return cmp;}}

通过 retrieveServiceLocked() 方法来解析 AndroidManifest.xml 文件中配置 Service 的 intent-filter 相关内容信息。

当解析完 Service 的 intent-filter 相关内容信息后,解析的结果会保存在 res.record 变量中。而 res 变量是一个 ServiceLookupResult 类型的对象,它的 record 变量则是一个 ServiceRecord 类型对象,用来表示一个 Service 。

ActiveServices.startServiceInnerLocked()

ActiveServices 的 startServiceLocked() 方法最后调用了 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()

调用 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);    // 调用 handleCreateService() 方法Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;}}}
}

bringUpServiceLocked() 方法首先通过 getProcessRecordLocked() 方法去获取 app 对象,它是一个 ProcessRecord 类型的对象,如果它不为空,说明 Service 要运行的进程已经存在。

Service 运行的进程有两种:

(1)一种是默认的,即运行在 Activity 启动 Service 的那个进程里,也就是说在哪个进程里调用了 startService() 方法,启动的 service 就运行在哪个进程里。

(2)一种是给 Service 一个单独的进程运行,比如在 AndroidManifest 文件里配置了如下内容:

//<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" 声明,这个声明用来实现 service 单独运行在 "xxx" 进程里。这样做的好处是, 即使应用程序无法工作,由于 service 单独运行在一个进程里,所以会继续工作 。

回到前面的方法,如果变量 app 为空,就代表 service 要运行的进程还没有启动,于是调用 startProcessLocked() 方法去启动一个新的进程。

如果 app 不为空,采用默认的方式启动 Service,最终调用到 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 对象,调用它的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() 方法通过调用 sendMessage() 方法来发送一个 msg 消息 ,当 Handler 接收到了 msg 消息之后,它会调用 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);    // 调用 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 加载进来,而参数 data.info.name 表示这个 Service 的名字, instantiateService() 方法是创建一个 Service 实例。接着, 创建一个 Context 对象 ,作为上下文环境之用。

handleCreateService() 方法最后调用了 service 的 onCreate() 方法 ,当这个方法被调用之后, 就会进入应用程序里 Service 的 onCreate() 方法 。

至此,Service 的启动就分析完毕,这个过程与启动 Activity 相比简单了很多。

总结

看到最后,希望这篇文章能帮你梳理清楚 “Service 的启动流程”

我整理了一些Activity的资料,如果你有需要可以私信我获取

还有Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅的精品资料

总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习

如果你有需要的话,可以点赞+评论关注我,然后私信我【学习】获取

service启动activity_「 Android 10 四大组件 」系列—Service 的 quot; 启动流程 quot;相关推荐

  1. java获取apk启动activity_兼容 Android 10 启动 APK 实现方案

    背景 我们想启动 APK 程序,有很多种方法,可以使用 Intent,也可以使用 adb shell 命令来启动,还有通过反射来启动 APk 程序. 我们这里主要讨论通过反射的方式来启动 apk 程序 ...

  2. Android深入四大组件(六)Android8.0 根Activity启动过程(前篇)

    相关文章 Android深入四大组件系列 Android系统启动系列 Android应用程序进程系列 Android深入解析AMS系列 前言 在几个月前我写了Android深入四大组件(一)应用程序启 ...

  3. Android深入四大组件(五)Android8.0 根Activity启动过程(后篇)

    前言 在几个月前我写了Android深入四大组件(一)应用程序启动过程(前篇)和Android深入四大组件(一)应用程序启动过程(后篇)这两篇文章,它们都是基于Android 7.0,当我开始阅读An ...

  4. Android深入四大组件(七)Android8.0 根Activity启动过程(后篇)

    相关文章 Android深入四大组件系列 Android系统启动系列 Android应用程序进程系列 Android深入解析AMS系列 前言 在几个月前我写了Android深入四大组件(一)应用程序启 ...

  5. Android深入四大组件(八)广播的注册、发送和接收过程

    前言 我们接着来学习Android四大组件中的BroadcastReceiver,广播主要就是分为注册.接收和发送过程.建议阅读此文前请先阅读Android深入理解四大组件系列的文章,知识重复的部分, ...

  6. Android之四大组件(AIDL Service的使用)

    跨进程调用Service(AIDL Service) Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信. 在前一篇文章(关于Android中的四大组件(Se ...

  7. Android实训课程之三 这次课老师先是提到了Android有四大组件:Activity、Service、Broadcast Receiver、Content Provider。然后重点提到Acti

    Android实训课程之三 这次课老师先是提到了Android有四大组件:Activity.Service.BroadcastReceiver.ContentProvider.然后重点提到Activi ...

  8. Android 之 四大组件、六大布局、五大存储

    Android 之四大组件.六大布局.五大存储:https://blog.csdn.net/shenggaofei/article/details/52450668 Android 四大组件.五大存储 ...

  9. Android的四大组件

    Android的四大组件:Activity.Service.BroadcastReceiver.Content Provider. Content Provider 属于Android应用程序的组件之 ...

最新文章

  1. 图解深度强化学习(简单的)
  2. 论文多次被拒怎么办?Best Paper Award获得者聊聊如何才能中顶会
  3. VBA读取固定文件夹中txt内容
  4. ai故障风字体_AI教程!3步搞定酷炫故障文字效果
  5. ppt背景图片php,ppt模板ppt背景图片 淡雅风格打包下载 (ppt如何打包)
  6. 西门子g120变频器接线图_西门子1500PLC通过工艺对象对G120变频器组态和调试
  7. pandas+groupby对南京二手房进行数据可视化及大图显示
  8. 房地产估值法研究报告_房地产估值方法
  9. dede修改描述description限制字数长度
  10. Kali Linux 2020.1安装教程
  11. python 发送邮件附件很慢_python发送邮件附件
  12. Mac系统下wow自动钓鱼python实现
  13. ogr 缓冲区_OGR几何关系与操作
  14. 奥比中光再度携手英伟达联合举办第三届3D视觉创新应用竞赛
  15. 淘宝如何做到懂你的推荐的?揭秘千人千面个性化推荐原理!
  16. 苹果手机怎么截屏,有哪些方面可以快速截屏
  17. linux系统下MYSQL备份与恢复
  18. 3点钟无眠区块链社区讨论成果汇总
  19. Python-SSH连接工具类
  20. linux中文件类型说明及文件权限

热门文章

  1. xampp php5.6 7.1共存,New XAMPP with PHP 7.2.8, 7.1.20, 7.0.31 5.6.37
  2. 火狐浏览器中打开java_将Firefox浏览器嵌入Java Swing中
  3. uboot的一般性介绍
  4. appium+java(五)微信小程序自动化测试实践
  5. 由百度 “PHP薪资” 引发的思考
  6. Linux的sort命令
  7. 《JavaScript高级程序设计》阅读笔记(一):ECMAScript基础
  8. loadrunner 配置远程监控windows服务器系统资源
  9. 签名程序集密钥文件路径
  10. 一个适用各类场合的Makefile模板