Android AMS拦截Activity启动

在 Android 开发中,我们常会遇到一些第三方组件(如 GMS)在特定场景下自动弹出 Activity 的情况。这些不合时宜的弹窗往往会干扰产品的正常业务逻辑,而由于我们无法直接修改 GMS 的内部代码,只能另辟蹊径从系统层面寻找解决方案。本文将详细介绍如何在 Framework 层通过拦截 Activity 启动流程,实现对特定 GMS Activity 的屏蔽。

问题背景:无法控制的 GMS 弹窗

GMS(Google Mobile Services)作为安卓生态的重要组成部分,其内部包含了大量服务和组件。在实际使用中,我们发现 GMS 会在某些触发条件下自动弹出特定 Activity(例如本文中涉及的com.google.android.gms.nearby.discovery.fastpair.HalfSheetActivity),这类弹窗并非我们业务所需,却会打断用户操作流程。

由于 GMS 属于闭源组件,我们无法通过常规的代码修改来禁用其弹窗逻辑。因此,我们将解决思路转向 Framework 层 ------ 通过拦截 Activity 的启动流程,对目标 Activity 进行过滤和阻断。

技术调研:Activity 启动流程与拦截点分析

要实现 Activity 的拦截,首先需要深入理解 Android 系统中 Activity 的启动机制。在 Android 的 Framework 层,Activity 的启动逻辑主要封装在ActivityStarter.java中,其中execute()方法是启动流程的核心入口。

scss 复制代码
int execute() {
    // 省略部分代码
    
    if (mRequest.activityInfo == null) {
        mRequest.resolveActivity(mSupervisor);
    }
    // 省略部分代码
    executeRequest()
    
    // 省略部分代码
}

通过分析源码可以发现,execute()方法会先解析待启动的 Activity 信息(mRequest.activityInfo),然后调用executeRequest()执行具体的启动操作。这意味着在executeRequest()调用前,目标 Activity 的相关信息(如组件名、包名等)已经准备完毕,这正是我们实现拦截的理想时机。

executeRequest()作为启动流程的关键节点,在此时进行拦截既能确保获取到完整的 Activity 信息,又能在启动操作执行前阻断流程,避免无效的资源消耗。

实现方案:在 ActivityStarter 中添加拦截逻辑

基于上述分析,我们确定在ActivityStarter.executeRequest()方法中添加拦截逻辑。具体实现步骤如下:

1. 定义拦截列表

首先,我们需要维护一个需要拦截的 Activity 列表(filterList),将目标 GMS Activity 的组件信息(包名 + 类名)纳入其中。组件名可以通过ComponentName.flattenToString()方法获取标准格式(如com.google.android.gms/com.google.android.gms.nearby.discovery.fastpair.HalfSheetActivity)。

2. 在启动流程中添加过滤判断

在executeRequest()方法中,当系统完成 Activity 信息解析且启动状态为START_SUCCESS时,我们对目标 Activity 进行拦截判断:

less 复制代码
if (err == ActivityManager.START_SUCCESS && aInfo != null) {
    for (String pkg : filterList) {
        // 对比当前启动的Activity与拦截列表中的组件信息
        if (pkg.equals(aInfo.getComponentName().flattenToString())) {
            Slog.w(TAG, "filter intent " + intent + "," + aInfo.getComponentName().flattenToString());
            // 将启动状态改为取消状态
            err = START_CANCELED;
        }
    }
}

这段代码的核心逻辑是:当检测到当前启动的 Activity 组件名存在于拦截列表中时,将启动结果err设置为START_CANCELED,从而阻断 Activity 的启动流程。

验证结果:拦截效果测试

为了验证拦截逻辑的有效性,我们通过 ADB 命令直接启动目标 GMS Activity 进行测试:

bash 复制代码
adb shell am start -n com.google.android.gms/com.google.android.gms.nearby.discovery.fastpair.HalfSheetActivity

执行命令后,系统返回如下结果:

vbnet 复制代码
Starting: Intent { cmp=com.google.android.gms/.nearby.discovery.fastpair.HalfSheetActivity }
Error: Activity not started, unknown error code -96

其中,错误码-96对应的正是我们在代码中设置的START_CANCELED状态,这表明拦截逻辑已成功生效 ------ 目标 Activity 的启动请求被系统拒绝,达到了预期的拦截效果。

总结与扩展

通过在 Framework 层的ActivityStarter中添加拦截逻辑,我们成功实现了对特定 GMS Activity 的屏蔽。这种方案的优势在于:

  1. 无需修改 GMS 源码,适用于闭源组件的管控场景;
  1. 拦截点位于 Activity 启动流程的早期阶段,能有效避免无效的页面绘制和资源加载;
  1. 通过列表配置的方式,便于扩展和维护需要拦截的目标 Activity。

在实际应用中,我们可以根据业务需求动态调整filterList,实现对不同场景下弹窗的精细化管控。同时,这种思路也可推广到其他需要拦截系统或第三方组件 Activity 的场景中,为 Android 系统定制提供一种可行的技术方案。

相关推荐
tongyiixiaohuang1 天前
WMS已发货状态反写金蝶云星空:单策略实战教程
android
好的佩奇1 天前
Dart 之类修饰符
android·flutter·dart
alexhilton1 天前
用Konsist与Lint强制执行设计系统契约
android·kotlin·android jetpack
北京自在科技1 天前
谷歌安卓 Gemini 迎来界面改版,Find Hub 接入 Gemini 支持物品记忆查找
android·安卓
YB13752 天前
Jetpack Compose 动画Modifier.animateItem()
android
2401_885885042 天前
巴林语音通知接口如何对接?系统告警语音API接入教程
android·前端·网络·python·语音识别
收纳过往2 天前
数据库加索引的时机:慢查询日志说话
android·开发语言·数据库·python·低代码·rxjava
狂热开发者2 天前
车载中控要给鸿蒙用户,能不能和 Android 共用一个二维码?
android·华为·harmonyos
.Bryce.2 天前
T2-LLM评测不等于Agent评测
android·java·人工智能·后端·gpt·agent·1024程序员节
美狐美颜SDK开放平台2 天前
视频美颜SDK如何应对快速转头与大幅度面部动作?
android·人工智能·ios·音视频·直播美颜sdk·视频美颜sdk