Android 12系统源码_页面管理(四)获取系统当前最上层的Activity信息
前言
很多应用开发人员,在日常开发过程中,经常会遇到一些需求,例如需要知道当前最上层的Activity是哪个,并结合这个Activity的名称来完成一些特定场景的需求。最简单的方法,是在创建Activity的时候将该Actvity存储到一个集合中,而当Activity销毁的时候,再将该Activity从集合中移除,这种方案虽然能够获取自己应用当前最上层的Activity是那个,但却无法获取除了自己应用以外的其他场景。犹豫谷歌为系统开发提供了特定的API,作为系统开发人员,我们完全可以通过这些API实时获取当前最上层的Activity信息,并将这些信息同步给系统应用。本篇文章我们将会结合Android12的系统源码,来探讨一下如何通过系统内部API实时获取当前系统最上层的Activity的信息,以及如何实时监听当前系统Activity栈信息的变化。
一、获取最上层的根任务信息
1、根任务是指包含一个或多个 Activity 的任务,并且没有父任务,根任务通常是由用户启动的应用程序或系统应用程序的主要任务。
在 Android 12 中,我们可以通过以下代码获取最上层的根任务信息。
IActivityManager ams = ActivityManager.getService(); //获取ActivityManagerService服务对象
List<ActivityManager.RunningTaskInfo> runningTasks = mAm.getTasks(1);;//调用getAllRootTaskInfos方法
首先调用ActivityManager的getService方法获取ActivityManagerService服务对象,然后调用该服务对象的getTasks(int maxNum) 方法,该方法会返回一个指定数量包含所有根任务信息的列表,每个根任务都有其任务 ID、根 Activity 的信息以及与之关联的其他活动堆栈。
2、来看下和RunningTaskInfo类相关的代码。
base/core/java/android/app/ActivityManager.java
public class ActivityManager {public static class RunningTaskInfo extends TaskInfo implements Parcelable {/*** 当前任务的唯一标识id* A unique identifier for this task.*/@Deprecatedpublic int id;/*** 当前任务状态的缩略图* Thumbnail representation of the task's current state.*/@Deprecatedpublic Bitmap thumbnail;/*** 当前任务的状态描述* Description of the task's current state.*/@Deprecatedpublic CharSequence description;/*** 当前任务中正在运行的Activity的数量* Number of activities that are currently running (not stopped and persisted) in this task.*/@Deprecatedpublic int numRunning;}
}
RunningTaskInfo类包含了当前任务对应的唯一标识ID、Bitmap类型的缩略图、状态描述以及该任务正运行的Activity的数量。
3、RunningTaskInfo继承自TaskInfo,继续来看下该类有哪些关键属性。
base/core/java/android/app/TaskInfo.java
public class TaskInfo {private static final String TAG = "TaskInfo";/*** 当前任务对应的用户id * The id of the user the task was running as if this is a leaf task. The id of the current* running user of the system otherwise.* @hide*/@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)public int userId;/*** 任务id* The identifier for this task.*/public int taskId;/*** 此任务中是否有正在运行的Activity* Whether or not this task has any running activities.*/public boolean isRunning;/*** 启动当前任务的Intent* The base intent of the task (generally the intent that launched the task). This intent can* be used to relaunch the task (if it is no longer running) or brought to the front if it is.*/@NonNullpublic Intent baseIntent;/*** The component of the first activity in the task, can be considered the "application" of this* task.*/@Nullablepublic ComponentName baseActivity;/*** 当前任务对应的Activity栈中的最上层正在显示的activity* The component of the top activity in the task, currently showing to the user.*/@Nullablepublic ComponentName topActivity;/*** The component of the target activity if this task was started from an activity alias.* Otherwise, this is null.*/@Nullablepublic ComponentName origActivity;/*** The component of the activity that started this task (may be the component of the activity* alias).* @hide*/@Nullablepublic ComponentName realActivity;/*** The number of activities in this task (including running).*/public int numActivities;/*** The last time this task was active since boot (including time spent in sleep).* @hide*/@UnsupportedAppUsagepublic long lastActiveTime;/*** 当前任务对应的屏幕设备id* The id of the display this task is associated with.* @hide*/public int displayId;/*** The feature id of {@link com.android.server.wm.TaskDisplayArea} this task is associated with.* @hide*/public int displayAreaFeatureId = FEATURE_UNDEFINED;/*** The recent activity values for the highest activity in the stack to have set the values.* {@link Activity#setTaskDescription(android.app.ActivityManager.TaskDescription)}.*/@Nullablepublic ActivityManager.TaskDescription taskDescription;/*** The locusId of the task.* @hide*/@Nullablepublic LocusId mTopActivityLocusId;/*** 当前任务是否支持分屏* True if the task can go in the split-screen primary stack.* @hide*/@UnsupportedAppUsagepublic boolean supportsSplitScreenMultiWindow;/*** 当前任务是否支持多窗口* Whether this task supports multi windowing modes based on the device settings and the* root activity resizability and configuration.* @hide*/public boolean supportsMultiWindow;/*** The resize mode of the task. See {@link ActivityInfo#resizeMode}.* @hide*/@UnsupportedAppUsagepublic int resizeMode;/*** The current configuration of the task.* @hide*/@NonNull@UnsupportedAppUsagepublic final Configuration configuration = new Configuration();/*** Used as an opaque identifier for this task.* @hide*/@NonNullpublic WindowContainerToken token;/*** 用于控制画中画模式的参数类* The PictureInPictureParams for the Task, if set.* @hide*/@Nullablepublic PictureInPictureParams pictureInPictureParams;/*** The {@link Rect} copied from {@link DisplayCutout#getSafeInsets()} if the cutout is not of* (LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES, LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS),* {@code null} otherwise.* @hide*/@Nullablepublic Rect displayCutoutInsets;/*** 当前任务最上层Activity的类型* The activity type of the top activity in this task.* @hide*/public @WindowConfiguration.ActivityType int topActivityType;/*** The {@link ActivityInfo} of the top activity in this task.* @hide*/@Nullablepublic ActivityInfo topActivityInfo;/*** Whether the direct top activity is in size compat mode on foreground.* @hide*/public boolean topActivityInSizeCompat;/*** Whether this task is resizable. Unlike {@link #resizeMode} (which is what the top activity* supports), this is what the system actually uses for resizability based on other policy and* developer options.* @hide*/public boolean isResizeable;/*** Relative position of the task's top left corner in the parent container.* @hide*/public Point positionInParent;/*** The launch cookies associated with activities in this task if any.* @see ActivityOptions#setLaunchCookie(IBinder)* @hide*/public ArrayList<IBinder> launchCookies = new ArrayList<>();/*** The identifier of the parent task that is created by organizer, otherwise* {@link ActivityTaskManager#INVALID_TASK_ID}.* @hide*/public int parentTaskId;/*** 当前任务是否持有焦点* Whether this task is focused.* @hide*/public boolean isFocused;/*** 当前任务是否可见* Whether this task is visible.* @hide*/public boolean isVisible;/*** Whether this task is sleeping due to sleeping display.* @hide*/public boolean isSleeping;}
TaskInfo类中也包含了很多对于当前任务至关重要的信息:任务对应的用户id、任务id、任务中是否有运行的Activity、启动任务的Intent、任务对应的Activity栈最上层Activity,对应的屏幕设备id、任务是否支持分屏、任务是否支持多窗口、用于控制画中画模式的参数类、任务是否持有焦点、任务是否可见等。
二、实时监听Activity栈信息变化。
1、我们主要是通过调用ActivityManagerService的相关方法来实时监听Activity对应的任务栈的变化的,具体可以参考以下代码。
//获取ActivityManagerService的实例对象IActivityManager am = ActivityManager.getService();//调用registerTaskStackListener方法,注册监听任务栈变化的回调对象am.registerTaskStackListener(new TaskStackListener() {@Overridepublic void onTaskStackChanged() throws RemoteException {final ActivityManager.RunningTaskInfo runningTask;try {//List<ActivityManager.RunningTaskInfo> runningTasks = mAm.getTasks(1);if (runningTasks == null) {return;}runningTask = runningTasks.get(0);} catch (RemoteException e) {e.printStackTrace();return;}if (runningTask == null) {return;}int displayId = runningTask.displayId;if (INVALID_DISPLAY != displayId && runningTask.topActivity != null) {String key = "display_" + displayId + "_top_activity";String packageName = runningTask.topActivity.getPackageName();String activityName = runningTask.topActivity.getClassName();String value = packageName + "/" + activityName;boolean isUpdate = !value.equals(mHashMapDisplayTopActivity.get(key));if (isUpdate) {Log.d(TAG, "updateTasks: key = " + key + " value = " + value);mHashMapDisplayTopActivity.put(key, value);}} }});;
对以上代码做个简单介绍:
- 我们可以通过调用ActivityManagerService的registerTaskStackListener方法注册回调对象,实时监听当前任务栈的变化。
- 继续调用ActivityManagerService的getTasks方法,获取当前正在运行的所有任务,该方法返回一个类型为RunningTaskInfo的集合,关于RunningTaskInfo这个类,前面我们已经做过简单介绍了。
- 最后结合RunningTaskInfo的相关属性,可以成功获取到当前系统中每个屏幕设备对应的最上层的Activity的包名和组件名称。
三、异常处理
不过在进行实测的时候发现,通过调用registerTaskStackListener方法注册的回调方法,有一定概率在页面发生切换的时候不会进行回调,比如应用异常崩溃,应用ANR被强制关闭等特殊情况,这个字段回调方法并没有执行,这就需要我们在这些事件发生的时候,通知AMS让其进行回调事件的调用。
相关文章:
Android 12系统源码_页面管理(四)获取系统当前最上层的Activity信息
前言 很多应用开发人员,在日常开发过程中,经常会遇到一些需求,例如需要知道当前最上层的Activity是哪个,并结合这个Activity的名称来完成一些特定场景的需求。最简单的方法,是在创建Activity的时候将该Actvity存储到一…...
RK3588开发板Ubuntu与开发板使用U盘互传
1 将 U 盘(U 盘的格式必须为 FAT32 格式,大小在 32G 以下)插到开发板的 usb 接口,串口打印信息如下所示,U 盘的设备节点是/dev/sdb4。U 盘的设备节点不是固定的,根据实际情况来查看设备节点。 2 输入以下命令挂载 U 盘,…...
【BUG】golang gorm导入数据库报错 “unexpected type clause.Expr“
帮同事排查一个gorm导入数据报错的问题 事发现场 ck sql CREATE TABLE ods_api.t_sms_jg_msg_callback_dis (app_key String DEFAULT COMMENT 应用标识,callback_type Int32 DEFAULT 0 COMMENT 0送达,1回执,channel Int32 DEFAULT 0 COMMENT uid下发的渠道,mode…...
TCP/IP网络模型
大家好我是苏麟 , 今天聊聊TCP/IP四层网络模型 . 资料来源 : 小林coding 小林官方网站 : 小林coding (xiaolincoding.com) 应用层 最上层的,也是我们能直接接触到的就是应用层(Application Layer),我们电脑或手机使用的应用软件都…...
github连不上
github连不上 错误提示解决方案steam 采用Hosts加速 错误提示 fatal: unable to access ‘https://github.com/Ada-design/qianduan.git/’: Failed to connect to github.com port 443 after 21073 ms: Couldn’t connect to server 解决方案 下载steam https://steampp.ne…...
Excel计算表达式的值
Excel如何求解表达式 其中第三种方法最简单,通过剪贴板实现 如,单元格A1中输入了 12345 然后在A2输入 “”&A1 然后复制A2,打开剪贴板,点击刚才复制的内容,就会在A2显示计算结果...
26元/月起!腾讯云一键自动搭建4核16G幻兽帕鲁服务器
腾讯云无需任何配置自动搭建幻兽帕鲁游戏联机服务器,游戏24小时在线,4核16G游戏联机服务器低至26元/月起,新手小白也能一键搭建属于自己的幻兽帕鲁游戏联机服务器! 第一步:购买游戏联机服务器 购买入口:htt…...
【C++游戏开发-01】推箱子
C游戏开发 文章目录 C游戏开发[TOC](文章目录) 前言一、逻辑分析1.1地图实现1.2人物的移动1.2.1小人移动1.2.2其他移动 1.3墙壁的碰撞1.4箱子的推动1.4.1什么时候推箱子1.4.2什么情况可以推箱子 1.5胜利的判断1.6卡关的处理1.7关卡的切换 二、DEMO代码2.1游戏框架2.2各功能函数…...
【lesson26】学习MySQL事务前的基础知识
文章目录 CURD不加控制,会有什么问题?CURD满足什么属性,能解决上述问题?什么是事务?为什么会出现事务事务的版本支持 CURD不加控制,会有什么问题? CURD满足什么属性,能解决上述问题&…...
持续积累分享金融知识
持续积累分享金融知识 一、什么是两融余额?二、什么是量化?三、散户可以进行量化投资么? 一、什么是两融余额? 两融余额是指投资者在融资买入和融券卖出交易中,通过向券商借入资金或证券进行交易,并且在交…...
网络协议 UDP协议
网络协议 UDP协议 在之前的文章中有对UDP协议套接字的使用进行讲解,本文主要对UDP协议进行一些理论补充。 文章目录 网络协议 UDP协议1. 概念2. UDP协议格式2.1 数据报长度2.2 校验和/检验和2.2.1 CRC校验2.2.2 MD5算法 1. 概念 UDP,即User Datagram P…...
爬虫笔记(三):实战qq登录
咳咳,再这样下去会进橘子叭hhhhhh 以及,这个我觉得大概率是成功的,因为测试了太多次,登录并且验证之后,qq提醒我要我修改密码才可以登录捏QAQ 1. selenium 有关selenium具体是啥,这里就不再赘述了&#x…...
又涨又跌 近期现货黄金价格波动怎么看?
踏入2024年一月的下旬,现货黄金价格可以说没了之前火热的状态,盘面上是又涨又跌。面对这样的行情,很多投资者不知道如何看了。下面我们就来讨论一下怎么把握近期的行情。 先区分走势类型。在现货黄金市场中有两种主要的走势类型,一…...
软件压力测试:探究其目的与重要性
随着软件应用在各行各业中的广泛应用,确保软件在高负载和极端条件下的稳定性变得至关重要。软件压力测试是一种验证系统在不同负载条件下的性能和稳定性的方法。本文将介绍软件压力测试的目的以及为什么它对软件开发和部署过程至关重要。 验证系统性能的极限&#x…...
Android.bp入门指南之浅析Android.bp文件
文章目录 Android.bp文件是什么?Android.bp的主要作用模块定义依赖关系构建规则模块属性插件支持模块的可配置性 为什么会引入Android.bp语法例子 Android.bp文件是什么? Android.bp 文件是 Android 构建系统(Android Build Systemÿ…...
2024年美赛 (D题ICM)| 湖流网络水位控制 |数学建模完整代码+建模过程全解全析
当大家面临着复杂的数学建模问题时,你是否曾经感到茫然无措?作为2022年美国大学生数学建模比赛的O奖得主,我为大家提供了一套优秀的解题思路,让你轻松应对各种难题。 让我们来看看美赛的D题! 完整内容可以在文章末尾领…...
安卓网格布局GridLayout
<?xml version"1.0" encoding"utf-8"?> <GridLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"android:layout_width"match_parent"android:la…...
DHCP简介
定义 动态主机配置协议DHCP(Dynamic Host Configuration Protocol)是一种用于集中对用户IP地址进行动态管理和配置的技术。即使规模较小的网络,通过DHCP也可以使后续增加网络设备变得简单快捷。 DHCP是在BOOTP(BOOTstrap Protoc…...
Hadoop生态系统中一些关键组件的详细解析
1. Hadoop核心组件 HDFS(Hadoop Distributed File System): 分布式文件存储系统。提供高吞吐量的数据访问,非常适合用于大规模数据集。有高容错性,通过在多个节点间复制数据块来实现。 MapReduce: 一种编程模型,用于在…...
功能强大的开源数据中台系统 DataCap 2024.01.1 发布
推荐一套基于 SpringBoot 开发的简单、易用的开源权限管理平台,建议下载使用: https://github.com/devlive-community/authx 推荐一套为 Java 开发人员提供方便易用的 SDK 来与目前提供服务的的 Open AI 进行交互组件:https://github.com/devlive-commun…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
