Android的AMS相关知识

2024-01-08 22:59
文章标签 android 知识 相关 ams

本文主要是介绍Android的AMS相关知识,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android7.0的AMS相关信息

  ActivityManager是一个和AMS相关联的类,它主要对运行中的Activity进行管理,这些管理工作并不是由ActivityManager来处理的,而是交由AMS来处理的。ActivityManager中的方法会通过ActivityManagerNative(AMN)的getDefault方法来得到ActivityManagerProxy(AMP),通过AMP就可以和AMN进行通信,而AMN是一个抽象类,它将功能交由它的子类AMS来处理,因此AMP就是AMS的代理类,AMS作为系统服务,很多API是不会暴露给ActivityManager的。
  在Activity的启动过程中,会调用Instrumentation的execStartActivity放,此方法中会调用AMN的getDefault来获取AMS的代理类AMP,接着调用AMP的startActivity方法。在getDefault方法中调用了gDefault的get方法,gDefault是一个Singleton类,先获取名为“activity”的Service引用,也就是IBinder类型的AMS的引用,接着将它封装成AMP类型对象,并将它保存到gDefault中,此后调用AMN的getDefault方法就会直接返回AMS的代理对象AMP。
  在asInterface方法中,descriptor值为android.app.IActivityManager类型,queryLocalInterface主要用来查询本地进程是否又IActivityManager接口的实现,有则返回,没有就将IBinder类型的AMS引用封装成AMP。在AMP的构造方法中将AMS的引用赋值给变量mRemote,这样在AMP中就可以使用AMS了。
  其中IActivityManager是一个接口,AMN和AMP都实现了这个接口,用于实现代理模式和Binder通信。AMP是AMN的内部类,在AMP的startActivity方法中,首先将传入的参数写入到Parcel类型的data中,通过IBinder类型对象mRemote(AMS的引用)向服务端的AMS发送了一个START_ACTIVITY_TRANSACTION类型的进程间通信请求,服务端的AMS就会从Binder线程池中读取客户端发来的数据,最终会调用AMN的onTransact方法,此方法会调用AMS的startActivity方法,最终调用startActivityAsUser,返回ActivityStarter的startActivityMayWait方法。
  AMP是AMN的内部类,它们都实现了IActivityManager接口,这样它们就可以实现代理模式,具体来讲是远程代理:AMP和AMN是运行在两个进程中的,AMP是client端,AMN是Server端,而Server端中具体的功能是由AMN的子类AMS来实现的,因此AMP就是AMS在client端的代理类。AMN又实现了Binder类,这样AMP和AMS就可以通过Binder来进行进程间通信。ActivityManager通过AMN的getDefault方法得到AMP,通过AMP就可以和AMS进行通信。

Android8.0的AMS相关信息

  Android8.0的AMS相关类与Android7.0的有一些差别,在Activity的启动过程中,会调用Instrumentation的execStartActivity方法,接着调用ActivityManager.getService方法,getService方法调用了IActivityManagerSingleton的get方法,IActivityManagerSingleton是一个Singleton类。先得到名为“activity”的Service引用,也就是IBinder类型的AMS应用,接着将它转换为IActivityManager类型的对象,采用的是AIDL,IActivityManager类是由AIDL工具在编译时自动生成的,IActivityManager.aidl的文件路径为frameworks/base/core/java/android/app/IActivityManager.aidl。要实现进程间通信,服务端也就是AMS只需要继承IActivityManager.Stub类并实现相应的方法就可以。采用AIDL后就不需要使用AMS的代理类AMP了。因此Android8.0去掉了AMP,代替它的是IActivityManager,它是AMS的本地代理。
  Android8.0的AMS相关类要简单的多,ActivityManager的getService方法会得到IActivityManager,AMS只需要继承IActivityManager.Stub类,就可以和ActivityManager实现进程间通信了。

AMS的启动过程

  AMS的启动是在SystemServer进程中启动的,从SystemServer的main方法开始,main方法只调用了SystemServer的run方法,先创建消息Looper,然后加载动态库libandroid_server.so。创建系统的Context,创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理,接着调用startBootstrapServices方法,用SystemServiceManager启动了ActivityManagerService、PowerManagerService、PackageManagerService等服务,然后调用startCoreServices方法启动了DropBoxManagerService、BatteryService、UsageStatsService和WebViewUpdateService。调用startOtherServices方法启动了CameraService、AlarmManagerService、VrManagerService等服务,这些服务的父类均为SystemService。官方把系统服务分为了三种类型,分别是引导服务、核心服务、其他服务。
  在startBootstrapServices方法中,调用了SystemServiceManager的startService方法,该方法参数为ActivityManagerService.Lifecycle.class。在startService中将service对象添加到ArrayList类型的mServices中来完成注册。然后调用service的onStart方法来启动Service对象。Lifecycle是AMS的内部类,在Lifecycle的构造方法中,创建了AMS实例,当调用了SystemService类型的service的onStart方法时,实际上是调用了AMS的start方法,Lifecycle的getService方法返回了AMS实例。这样在SystemServer的startBootstrapServices方法中mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService实际得到的就是AMS实例。

AMS与应用程序

  Zygote的Java框架层中,会创建一个Server端的Socket,这个Socket用来等待AMS请求Zygote来创建新的应用程序进程。要启动一个应用程序,首先要保证这个应用程序所需要的进程已经存在。在启动应用程序时AMS会检查这个应用程序需要的进程是否存在,不存在就会请求Zygote进程创建需要的应用程序进程。已Service为例,Service在启动过程中会调用ActivityServices的bringUpServiceLocked方法,先得到ServiceRecord的processName的值并赋值给procName,其中processName用来描述Service想要在哪个进程运行,默认是当前进程,也可以在AndroidManifest文件中设置android:process属性来新开启一个进程运行Service。将procName和Service的uid传入到AMS的getProcessRecordLocked方法中,来查询是否存在一个与Service对应的ProcessRecord类型的对象app,ProcessRecord主要用来描述运行的应用程序进程的信息。如果Service对应的app为null则说明用来运行Service的应用程序进程不存在,则调用AMS的startProcessLocked方法来创建对应的应用程序进程;如果用来运行Service的应用程序进程存在,则调用realStartServiceLocked方法来启动Service。
  AMS与应用程序进程的关系主要有以下两点:

  • 启动应用程序时AMS会检查这个应用程序需要的应用程序进程是否存在。
  • 如果需要的应用程序进程不存在,AMS就会请求Zygote进程创建需要的应用程序进程。
AMS重要的数据结构
解析ActivityRecord

  内部记录了Activity的所有信息,用来描述了一个Activity,在启动Activity时被创建的,具体时在ActivityStarter的startActivity方法中被创建的。
  ActivityRecord的重要成员变量:

名称类型说明
serviceActivityManagerServiceAMS的引用
infoActivityInfoActivity中代码和AndroidManifest设置的节点信息,比如launchMode
launchedFromPackageString启动Activity的包名
taskAffinityStringActivity希望归属的栈
taskTaskRecordActivityRecord所在的TaskRecord
appProcessRecordActivityRecord所在的应用程序进程
stateActivityState当前Activity的状态
iconintActivity的图标资源标识符
themeintActivity的主题资源标识符

  ActivityRecord的作用,其内部存储了Activity的所有信息,包括AMS的引用,AndroidManifest节点信息,Activity状态,Activity资源信息和Activity进程相关信息。

解析TaskRecord

  TaskRecord用来描述一个Activity任务栈

名称类型说明
taskIdint任务栈的唯一标识符
affinityString任务栈的倾向性
intentIntent启动这个任务栈的Intent
mActivitiesArrayList< ActivityRecord>按照历史顺序排列的Activity记录
mStackActivityStack当前归属的ActivityStack
mServiceActivityManagerServiceAMS的引用

  TaskRecord的作用,其内部存储了任务栈的所有信息,包括任务栈的唯一标识符、任务栈的倾向性、任务栈中的Activity记录和AMS的引用等。

解析ActivityStack

  ActivityStack是一个管理类,用来管理系统所有Activity,其内部维护了Activity的所有状态、特殊状态的Activity以及和Activity相关的列表数据。ActivityStack是由ActivityStackSupervisor来进行管理的,而ActivityStackSupervisor在AMS的构造方法中被创建,在createStackSupervisor方法中创建了ActivityStackSupervisor。

ActivityStack的实例类型

  在ActivityStackSupervisor中由多种ActivityStack,mHomeStack用来存储Launcher App的所有Activity,mFocusedStack表示当前正在接收输入或启动下一个Activity的所有Activity,mLastFocusedStack表示此前接收输入的所有Activity。通过ActivityStackSupervisor提供了获取上述ActivityStack的方法,比如要获取mFocusedStack,只需要调用ActivityStackSupervisor的getFocusedStack方法就可以了。

ActivityState

  再ActivityStack中通过枚举存储了Activity的所有状态。

enum ActivityState {INITIALIZING,RESUMED,PAUSING,PAUSED,STOPPING,STOPPED,FINISHING,DESTROYING,DESTROYED
}

  overridePendingTransition方法用于设置Activity的切换动画,可以看到只有ActivityState为RESUMED状态或者PAUSING状态时才会调用WMS类型的mWindowManager对象的overridePendingAppTransition方法来切换动画。

特殊状态的Activity

mPausingActivity: 正在暂停的Activity
mLastPausedActivity:上一个已暂停的Activity
mLastNoHistoryActivity:最近一次没有历史记录的Activity
mResumedActivity:已经resume的Activity
mLastStartedActivity:最近一次启动的Activity
mTranslucentActivityWaiting:传递给convertToTranslucent方法最上层的Activity

维护的ArrayList

  在ActivityState中维护了很多ArrayList

ArrayList元素类型说明
mTaskHistoryTaskRecord所有没有被销毁的Activity任务栈
mLRUActivitiesActivityRecord正在运行的Activity,列表中第一个条目时最近最少使用的Activity
mNoAnimActivitiesActivityRecord不考虑转换动画的Activity
mValidateAppTokensTaskGroup用于与窗口管理器验证应用令牌
Activity任务栈模型

Activity任务栈
  ActivityRecord用来记录一个Activity的所有信息,TaskRecord中包含了一个或多个ActivityRecord,TaskRecord用来表示Activity的任务栈,用来管理栈中的ActivityRecord,ActivityStack又包含了一个或多个TaskRecord,它是TaskRecord的管理者。Activity栈管理就是建立在Activity任务栈模型上的,有了栈管理,可以对应用程序进行操作,应用可以服用自身应用中以及其他应用的Activity,节省了资源。

LaunchMode
  1. standard:默认模式,每次启动Activity都会创建一个新的Activity实例。
  2. singleTop:如果要启动的Activity已经在栈顶,则不会重新创建Activity,同时该Activity的onNewIntent方法会被调用;如果要启动的Activity不在栈顶,则会重新创建该Activity的实例。
  3. singleTask:如果要启动的Activity已经存在于它想要归属的栈中,那么不会创建该Activity实例,将栈中位于该Activity上的所有的Activity出栈,同时该Activity的onNewIntent方法会被调用。如果要启动的Activity不存在与它想要归属的栈中,并且该栈存在,则会重新创建该Activity的实例;如果要启动的Activity想要归属的栈不存在,则首先要创建一个新栈,然后创建该Activity实例并压入栈中。
  4. singleInstance:和singleTask基本类似,不同的是启动Activity时,首先要创建一个新栈,然后创建该Activity实例并压入新栈中,新栈只会存在这一个Activity实例。
Intent的FLAG

  在Intent中定义了很多FLAG,其中几个FLAG也可以设定Activity的启动方式。

  • FLAG_ACTIVITY_SINGLE_TOP:同singleTop效果一样
  • FLAG_ACTIVITY_NEW_TASK:同singleTask效果一样
  • FLAG_ACTIVITY_CLEAR_TOP:如果要启动的Activity已经存在于栈中,则将所有位于它上面的Activity出栈,singleTask默认具有此标记位的效果。
  • FLAG_ACTIVITY_NO_HISTORY:Activity一旦退出就不会存在于栈中,也可以在AndroidManifest.xml中设置Android:noHistory。
  • FLAG_ACTIVITY_MULTIPLE_TASK:需要和FLAG_ACTIVITY_NEW_TASK一同使用才效果,系统会启动一个新的栈来容纳新启动的Activity。
  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS:Activity不会被放入到“最近启动的Activity”列表中。
  • FLAG_ACTIVITY_BROUGHT_TO_FRONT:这个标志位通常不是由应用程序中的代码设置的,而是LaunchMode为singleTask时,由系统自动加上的。
  • FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY:这个标志位通常不是由应用程序中的代码设置的,而是从历史记录启动的(长按Home键调出)Activity由系统添加的。
  • FLAG_ACTIVITY_CLEAR_TASK:需要和FLAG_ACTIVITY_NEW_TASK一同使用才有效果,用于清除于启动的Activity相关栈的所有其他Activity。
      Activity启动时会调用AMS的startActivity方法,经过层层调用会调用ActivityStarter的startActivityUnchecked方法,setInitialState用于初始化启动Activity的各种配置,在初始化前会重置各种配置再进行配置,这些配置包括ActivityRecord、Intent、TaskRecord和LaunchFlags(Activity启动的FLAG)等。computeLaunchingTaskFlags方法用于计算出Activity启动的FLAG,并将计算的值赋值给mLaunchFlags,然后将mLaunchFlags设置给Intent,达到设定Activity的启动方式的目的。
      计算启动的FLAG的逻辑比较复杂,当TaskRecord类型的mInTask为null时,说明Activity要加入的栈不存在。ActivityRecord类型的mSourceRecord用于描述“初始Activity”,当mSourceRecord为null且FLAG_ACTIVITY_NEW_TASK时需要创建一个新栈,如果“初始Activity”所在的栈只允许有一个Activity实例,则也需要创建一个新栈;如果LaunchMode设置了singleTask或singleInstance则也要创建一个新栈。
taskAffinity

  可以在AndroidManifest.xml中设置android:taskAffinity,用来指定Activity希望归属的栈,在默认情况下,同一个应用程序的所有的Activity都有着相同的taskAffinity。

  1. taskAffinity于FLAG_ACTIVITY_NEW_TASK或者singleTask配合。如果新启动Activity的taskAffinity和栈的taskAffinity相同则加入到该栈中;如果不同,就会创建新栈。
  2. taskAffinity与allowTaskReparentingpeihe。如果allowTaskReparenting为true,说明Activity具有转移的能力。当社交应用启动发送邮件Activity,此时二者处于同一个栈中,且这个栈位于前台;如果发送邮件Activity的allowTaskReparenting为true,此后E-mail应用所在栈位于前台时,发送邮件的Activity就会由社交应用栈转移到邮件应用栈(taskAffinity相同)。taskAffinity对应的代码在ActivityStack的findTaskLocked中,遍历mTaskHistory列表,列表元素为TaskRecord,用于存储没有被销毁的栈,对每一个栈的信息,将栈的rootAffinity(初始的taskAffinity)和目标Activity的taskAffinity做对比,如果相同,则将FindTaskResult的matchByRootAffinity属性设置为true,说明找到了匹配的栈。

这篇关于Android的AMS相关知识的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/585134

相关文章

RecastNavigation之Poly相关类

Poly分成正常的Poly 和 OffMeshPoly。 正常的Poly 又分成 原始的Poly 和 Detail化的Poly,本文介绍这两种。 Poly的边分成三种类型: 1. 正常边:有tile内部的poly与之相邻 2.border边:没有poly与之相邻 3.Portal边:与之相邻的是外部tile的poly   由firstLink索引 得到第一个连接的Poly  通

[职场] 公务员的利弊分析 #知识分享#经验分享#其他

公务员的利弊分析     公务员作为一种稳定的职业选择,一直备受人们的关注。然而,就像任何其他职业一样,公务员职位也有其利与弊。本文将对公务员的利弊进行分析,帮助读者更好地了解这一职业的特点。 利: 1. 稳定的职业:公务员职位通常具有较高的稳定性,一旦进入公务员队伍,往往可以享受到稳定的工作环境和薪资待遇。这对于那些追求稳定的人来说,是一个很大的优势。 2. 薪资福利优厚:公务员的薪资和

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

android 免费短信验证功能

没有太复杂的使用的话,功能实现比较简单粗暴。 在www.mob.com网站中可以申请使用免费短信验证功能。 步骤: 1.注册登录。 2.选择“短信验证码SDK” 3.下载对应的sdk包,我这是选studio的。 4.从头像那进入后台并创建短信验证应用,获取到key跟secret 5.根据技术文档操作(initSDK方法写在setContentView上面) 6.关键:在有用到的Mo

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

Android我的二维码扫描功能发展史(完整)

最近在研究下二维码扫描功能,跟据从网上查阅的资料到自己勉强已实现扫描功能来一一介绍我的二维码扫描功能实现的发展历程: 首页通过网络搜索发现做android二维码扫描功能看去都是基于google的ZXing项目开发。 2、搜索怎么使用ZXing实现自己的二维码扫描:从网上下载ZXing-2.2.zip以及core-2.2-source.jar文件,分别解压两个文件。然后把.jar解压出来的整个c

android 带与不带logo的二维码生成

该代码基于ZXing项目,这个网上能下载得到。 定义的控件以及属性: public static final int SCAN_CODE = 1;private ImageView iv;private EditText et;private Button qr_btn,add_logo;private Bitmap logo,bitmap,bmp; //logo图标private st

Android多线程下载见解

通过for循环开启N个线程,这是多线程,但每次循环都new一个线程肯定很耗内存的。那可以改用线程池来。 就以我个人对多线程下载的理解是开启一个线程后: 1.通过HttpUrlConnection对象获取要下载文件的总长度 2.通过RandomAccessFile流对象在本地创建一个跟远程文件长度一样大小的空文件。 3.通过文件总长度/线程个数=得到每个线程大概要下载的量(线程块大小)。

SQL Server中,always on服务器的相关操作

在SQL Server中,建立了always on服务,可用于数据库的同步备份,当数据库出现问题后,always on服务会自动切换主从服务器。 例如192.168.1.10为主服务器,12为从服务器,当主服务器出现问题后,always on自动将主服务器切换为12,保证数据库正常访问。 对于always on服务器有如下操作: 1、切换主从服务器:假如需要手动切换主从服务器时(如果两个服务

时间服务器中,适用于国内的 NTP 服务器地址,可用于时间同步或 Android 加速 GPS 定位

NTP 是什么?   NTP 是网络时间协议(Network Time Protocol),它用来同步网络设备【如计算机、手机】的时间的协议。 NTP 实现什么目的?   目的很简单,就是为了提供准确时间。因为我们的手表、设备等,经常会时间跑着跑着就有误差,或快或慢的少几秒,时间长了甚至误差过分钟。 NTP 服务器列表 最常见、熟知的就是 www.pool.ntp.org/zo