百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

Android 中怎么使用IActivitymanager

feilongw 2025-05-14 08:07 16 浏览

Android 操作系统之 Activity 的启动过程

前言

上篇文章写到 Service 的启动过程; 相对来说Activity的启动过程比Service的启动过程更为复杂,其一Activity的生命周期方法比Service多,其二Activity具有启动模式和返回栈; 写本文的目的在于更清晰的梳理Activity的启动过程,加强自己的内功修炼,博客粉丝日益增多,力在以最简单的方式让大家理解,跟大家一起学习

一、Binder的基本理解

Activity的启动有多次IPC过程,所以Binder属于预备知识,帮助我们更好理解系统的C/S的这种架构模式

二、Activity启动的双向IPC过程

一般Android各个应用进程的启动都以这样一条路线,init进程 –> Zygote进程 –> SystemServer进程 –>各种应用进程

  • Init进程:Linux的根进程,Android系统是基于Linux系统的,因此可以算作是整个android操作系统的第一个进程;
  • Zygote进程是所有应用进程的父进程,所有的应用进程都是它孵化出来的;
  • SystemServer进程含有一些核心的服务,比如ActivityManagerService,PackageManagerService,WindowManagerService等;
  • 各种应用进程:启动自己编写的客户端应用时,有自己的虚拟机与运行环境。

由此可知应用的第一个Activity的启动是多个进程相互配合的结果,多个进程相互配合就少不了使用Binder进行IPC了,现在看一次IPC调用的过程是怎样的。


上图大概说明了一次IPC的过程,或许你现在对里面各个类还不是很清楚,没关系,大致了解一下

ActivityManagerService (下文简称AMS),AMS是Android中最核心的服务,实现了ActivityManager,主要负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作,AMS提供了一个ArrayList mHistory来管理所有的Activity,Activity在AMS中的形式是ActivityRecord,Task在AMS中的形式为TaskRecord,进程在AMS中的管理形式为ProcessRecord,它在Android中特别重要

ActivityManagerNative (下文简称AMN):由于AMS是系统核心服务在SystemServer进程里面,很多API不能直接开放供客户端使用,所以需要通过IPC的方式,具体是这样的,ActivityManager类内部调用AMN的getDefault函数得到一个ActivityManagerProxy对象,通过它可与AMS通信

ActivityManagerProxy (下文简称AMP):AMP是AMS在客户端进程的一个代理,通过AMP里面的方法请求AMS

Instrumentation: Instrumentaion是一个工具类,一个大管家。当它被启用时,系统先创建它,再通过它来创建其他组件;另外,系统和组件之间的交互也将通过Instrumentation来传递,这样,Instrumentation就能监测系统和这些组件的交互情况了。在实际使用中,我们可以创建Instrumentation的派生类来进行相应的处理。Android中Junit的使用到了Intrstrumentation

OK,现在我们知道,Activity是如何向AMS发出startActivity这个请求了,这意味着Activity可以与AMS进行通信,但是AMS却不能与Activity通信,Binder是单向的,所以在Activity发出请求之后,AMS需要通知Activity发生状态改变,要做到这一点,自然就在AMS到Activity这个过程建立一个Binder,如下:


大致过程就是,SystemServer进程在收到请求后,再通过IPC向应用进程发送scheduleLaunchActivity请求,应用进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息,主线程在收到Message后,创建目标Activity,并回调Activity.onCreate()等方法

对上面的理解不是太明白,在看下面这张图,简单多了;AMS到Activity这个过程建立了一个Binder,Activity到AMS这个过程也建立了一个Binder,这就能相互通信了


上图就是Activity与AMS之间的双向Binder连接, (备注:这个就是理解Activity启动流程的指南针,不记住这个,复杂的启动流程会让你晕头转向);Activity用IActivityManager提供的API向AMS提出执行某个动作的请求(本例中是启动RemoteService),AMS通过IApplicationThread提供的API来控制Activity所在的应用程序,这些API包括schedulePauseActivity()、scheduleStopActivity()等

IActivityManager接口定义的API,启动四大组件的等多种请求都在里面


IApplicationThread接口定义的API,一看就比IActivityManager高逼格一点,IActivityManager好多方法是start开头,表示去AMS请求,IApplicationThread以schedule开头,表示对Activity进行调度


分析到这里,我们不知不觉间忽略了两个问题,那就是启动Activity至少需要两个前提

第一是,应用进程存在,第二AMS已经初始化完毕; 在调用startActivity方法时候,如果我们的应用进程不存在,Activity能启动吗,当然是不能的,比如点击桌面图标的时候,这个时候需要先创建进程。关于Zygote孵化应用进程,这个暂时不说,先看看AMS服务注册

三、AMS服务注册

先忽略 Activity调用ActivityManagerService启动应用,直接从SystemServer的main方法说起

 /**
    * The main entry point from zygote.
    */
   public static void main(String[] args) {
       new SystemServer().run();
   }

run方法中,调用了startBootstrapServices

 private void startBootstrapServices() {
      
       ......
       //启动AMS服务
       Installer installer = mSystemServiceManager.startService(Installer.class);

       //请注意这里参数是Lifecycle,因为AMS是在Lifecycle里面new出来的
       mActivityManagerService = mSystemServiceManager.startService(
               ActivityManagerService.Lifecycle.class).getService();
       mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
       mActivityManagerService.setInstaller(installer);

       mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

       mActivityManagerService.initPowerManagement();

        ......
       mActivityManagerService.setSystemProcess();
     ......
}
 public SystemService startService(String className) {
       final Class serviceClass;
       try {
           serviceClass = (Class)Class.forName(className);
       } catch (ClassNotFoundException ex) {
           Slog.i(TAG, "Starting " + className);
       }
       return startService(serviceClass);
   }

继续

public  T startService(Class serviceClass) {
       try {
           final String name = serviceClass.getName();
           // 1、创建服务
           final T service;
           try {
               Constructor constructor = serviceClass.getConstructor(Context.class);
             // 如果传进来的是ActivityManagerService.Lifecycle对象,那么ActivityManagerService就能被创建
               service = constructor.newInstance(mContext);
           } catch (InstantiationException ex) {
               throw new RuntimeException("Failed to create service " + name
                       + ": service could not be instantiated", ex);
           }
           // 2、注册服务
           mServices.add(service);

           // 3、启动服务
           try {
               service.onStart();
           } catch (RuntimeException ex) {
               throw new RuntimeException("Failed to start service " + name
                       + ": onStart threw an exception", ex);
           }
           return service;
       } finally {
           Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
       }
   }
ActivityManagerService.java

  public static final class Lifecycle extends SystemService {
       private final ActivityManagerService mService;

       public Lifecycle(Context context) {
           super(context);
         //ActivityManagerService被new出来了
           mService = new ActivityManagerService(context);
       }

       @Override
       public void onStart() {
         //  启动
           mService.start();
       }

       public ActivityManagerService getService() {
           return mService;
       }
   }
 private void start() {
       Process.removeAllProcessGroups();
       mProcessCpuThread.start();

       mBatteryStatsService.publish(mContext);
       mAppOpsService.publish(mContext);
       Slog.d("AppOps", "AppOpsService published");
       LocalServices.addService(ActivityManagerInternal.class, new LocalService());
   }

回到 startBootstrapServices里面调用的
mActivityManagerService.setSystemProcess();

public void setSystemProcess() {
       try {
           ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
           ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
           ServiceManager.addService("meminfo", new MemBinder(this));
           ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
           ServiceManager.addService("dbinfo", new DbBinder(this));
           ......


      // 设置application info LoadedApkinfo 有关 framework-res.apk
       ApplicationInfo info = mContext.getPackageManager().getApplicationInfo( "android", STOCK_PM_FLAGS);
       mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());
       
       //给SystemServer进程创建ProcessRecord,adj值,就是将SystemServer进程加入到AMS进程管理机制中,跟应用进程一致
       synchronized (this) {
           ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
           app.persistent = true;
           app.pid = MY_PID;
           app.maxAdj = ProcessList.SYSTEM_ADJ;
           app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
           synchronized (mPidsSelfLocked) {
               mPidsSelfLocked.put(app.pid, app);
           }
           updateLruProcessLocked(app, false, null);
           updateOomAdjLocked();
 }

ServiceManager这里面注册了很多的服务,可通过dumpsys <服务名>命令查看。比如查看CPU信息命令dumpsys cpuinfo,查看graphics信息命令dumpsys gfxinfo

在Android中所有的核心服务,并不是直接给上层使用,都先交给ServiceManager管理,上层使用的时候可以从ServiceManager获取,ServiceManager相当于一个路由作用。现在来看一张经典的图。其中注册服务,获取服务以及使用服务,每一次都是一个完整的Binder IPC过程,可见理解Binder是多么的重要啊。关于AMS启动得深入了解


  • 注册服务:首先AMS注册到ServiceManager。AMS所在进程(SystemServer)是客户端,ServiceManager是服务端
  • 获取服务:Client进程使用AMS前,须先向ServiceManager中获取AMS的代理类AMP。该过程。AMP所在进程(应用进程)是客户端,ServiceManager是服务端
  • 使用服务: app进程根据得到的代理类AMP,便可以直接与AMS所在进程交互。该过程,AMP所在进程(应用进程)是客户端,AMS所在进程(SystemServer)是服务端

有需要文章中完整代码的同学 现在私信发送 “底层源码” 即可免费获取

现在私信发送 “进阶” 还可以获取《更多 Android 源码解析+核心笔记+面试真题》

最后我想说:

学习没有捷径可言,我们要注意记学习,不仅要记,还要写心得体会,文字笔记、画图、总结等,方式很多,但是一定要自己认真去做,不要太相信自己的记忆,只有反复记忆,加深理解才行

同时,对于程序员而言,不单单是死记硬背,我们有更好的方式去学习,比如写demo去验证。复习知识点时,要及时跟你做过的项目结合起来,这样在面试时就知道怎么聊了,由项目讲到知识点,由一个知识点串联到另一个知识点。复习到一定阶段,可以尝试着去把这些东西串联起来,由点及面,形成知识体系

对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们

技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

Android 架构师之路还很漫长,与君共勉

相关推荐

ESP32 LED显示屏圆形表盘 esp32驱动显示屏

ESP32开发板的电压引脚有哪些ESP32开发板上的电压引脚提供为开发板供电所需的电压。ESP32开发板具有三个电压引脚,分别标记为3V3、5V/VN和GND。这些电压引脚具有不同的功能,可...

Java DB番号(javadb的下载地址在哪里)

穿着Prada的恶魔阿斯顿马丁DB11●直接跳入DB11的AstonMartin指标性番号●全新升V12双涡轮增压心脏入替●年中即可能现身宝岛作为全球最多车迷倾心爱恋的GT跑车,关注AstonMa...

LENOVO服务器登录管理口的方法

常用服务器管理口IP及账号密码(欢迎补充)文章包含各种型号的服务器管理口的ip地址大全,以便于我们方便访问服务器的相关日志,管理硬件信息,远程登录等等HP管理口:ILO默认用户/密码:Adminis...

Android 滑动2次退出app

AndroidBeta3提供全新应用关闭方式,适合无法滑动的用户#头条精品计划#快速导读AndroidBeta3已正式发布,带来了微小但重要的变化,特别是在应用管理方面。新的“关闭”...

jenkins 看不到workspace任务

Jenkins(7)参数化构建配置和远程服务器部署一、前言本文主要实现jenkins的参数化构建配置和远程服务器部署,其它操作可自行研究。二、参数化构建配置1、安装插件ExtendedChoice...

delphi uniDac(delphi unidac有连接池吗)

C++开发人员有了新选择,C++Builder社区版新鲜出炉#长文创作激励计划#对于个人编程爱好者,学习C++,是提高编程能力的一种重要途径。如今,C++开发人员有了新选择,C++Builder...

linux 磁盘存储空间_linux磁盘空间满了怎么清理

Android允许Linux终端使用手机全部存储空间IT之家4月日消息,谷歌Pixel手机正朝着成为强大便携式计算设备的目标迈进。年3月的更新中,Linux终端应用的推出为这一转...

Android 监听白天黑夜模式

Android监听滚动视图AndroidUILibs之Android-ObservableScrollView1.说明Android-ObservableScrollView,顾名思义,Andr...

linux安装chome_Linux安装MySQL5.7

Centos7如何安装google-chrome浏览器一.配置yum源在目录/etc/yum.repos.d/下新建文件google-chrome.repovim/etc/yum.repos...

centos无法粘贴(linux系统无法粘贴文件)

CentOS7复制文件显示进度今天给大家分享一个CentOS7下的实用小工具,挺实用的。欢迎拿去使用,引用请注明来源作者,共同学习。一、cp命令简介CentOS7自带的cp、mv命令是不支持显示进度...

ios 版的steam app无法连接 steam app连接不到服务器

网络正常但steam无法连接服务器图文解决教程网络正常但steam无法连接服务器图文解决教程在享受Steam平台带来的游戏乐趣时,有时玩家会遇到网络正常却无法连接至Steam服务器的情况,这无疑打乱了...

ios越狱 软件app(苹果ios越狱软件)

告别千篇一律,iOS越狱插件K2geIsland玩转iPhone灵动岛IT之家2月日消息,科技媒体idownloadblog今天(2月日)发布博文,报道称开发者mafu最新推出...

java工资管理系统设计论文 工资管理系统程序设计

深度解析|员工考勤工资智慧管理系统的建设与开发方案导读:本文将从员工考勤工资智慧管理系统的开发目的、开发背景、目标用户、系统设计、系统架构、主要功能模块等方面进行分析,软件主要功能包括:按照工种统...

JAVA中setAttribute没有生效 java setattribute用法

JSPrequest.setAttribute()详解及实例这篇文章主要介绍了javascriptrequest.setAttribute()详解及实例的相关资料,需要的朋友可以参考下java...

51单片机原理以及接口技术(一)-单片机发展概述

单片机知识重点汇总一,想学习单片机的朋友不要错过单片机知识重点汇总一主要性能:  与MCS-单片机产品兼容、8K字节在系统可编程Flash存储器、次擦写周期、全静态操作:0Hz~33Hz、三级加...