Android 12:在 ActivityStarter 层拦截分享、搜索与 HTTP 外链

场景:客户自研 Launcher,需要在系统侧限制第三方应用通过 TextView 链接跳转、文本/图片分享等路径离开业务界面。Android 12 起,与「能否启动 Activity」强相关的逻辑集中在 wm 模块的 ActivityStarter 中,适合在此做统一拦截。

1. 背景与入口位置

  • Android 12 变更 :应用启动相关逻辑中,ActivityStarter 已从传统 am 侧迁移到窗口管理侧,源码路径为:
    frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
  • 拦截思路 :在解析 Intent、得到可启动目标(ResolveInfo 等)之后,根据 action、data 等特征直接放弃解析结果(例如将 rInfo 置空),使后续流程无法找到可启动组件,等价于「禁止启动」。

2. 拦截分享、网页搜索与 http(s) 浏览

在 ActivityStarter 中合适位置(需与你们工程里 err、intent、rInfo 等变量生命周期一致)增加类似逻辑:对 ACTION_SEND / ACTION_SEND_MULTIPLE / ACTION_WEB_SEARCH 一律忽略;对 ACTION_VIEW 且 data scheme 为 http/https 的,除打日志外可在主线程弹出提示,并同样清空解析结果。

frameworks\base\services\core\java\com\android\server\wm\ActivityStarter.java

java 复制代码
// 屏蔽发送、分享及搜索
String action = intent.getAction();
Context context = mService.mUiContext;  // 获取可用于弹 Toast 等的 UI 上下文
if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)
        || Intent.ACTION_WEB_SEARCH.equals(action)) {
    Slog.w(TAG, "ignore an intent: " + intent);
    rInfo = null;
} else if (Intent.ACTION_VIEW.equals(action) && intent.getData() != null) {
    String scheme = intent.getData().getScheme();
    if (scheme != null && scheme.startsWith("http")) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(context, "该功能暂不可使用", Toast.LENGTH_SHORT).show();
            }
        });
        rInfo = null;
        Slog.w(TAG, "ignore an intent: " + intent);
    }
}

说明要点:

  • ACTION_SEND / ACTION_SEND_MULTIPLE:覆盖系统分享、多选分享等入口。
  • ACTION_WEB_SEARCH:覆盖「网页搜索」类 Intent。
  • ACTION_VIEW + http:覆盖浏览器打开链接;若业务仍允许 tel:、mailto: 等,可在分支中按 scheme 细化。
  • rInfo = null 后需保证与原有错误码、err 赋值逻辑一致,避免出现不一致的启动结果(需结合你们补丁前后完整编译与 CTS/冒烟验证)。

3. mUiContext 从何而来(ActivityTaskManagerService)

截图对应 ActivityTaskManagerService 构造函数片段:系统在创建 ATMS 时会保存当前系统进程的 ActivityThread,并从中取出 系统 UI 上下文 ,供需要与用户界面交互的系统服务使用(例如上述 Toast)。

frameworks\base\services\core\java\com\android\server\wm\ActivityTaskManagerService.java

java 复制代码
public ActivityTaskManagerService(Context context) {
    mContext = context;
    mFactoryTest = FactoryTest.getMode();
    mSystemThread = ActivityThread.currentActivityThread();
    mUiContext = mSystemThread.getSystemUiContext();
    // ... ClientLifecycleManager、WindowOrganizerController 等初始化
}

因此 ActivityStarter 里通过 mService.mUiContext(具体字段名以你们分支为准)拿到的,本质上是 ActivityThread.currentActivityThread() 关联的 getSystemUiContext(),与「普通应用进程里用 Activity 拿到的 Context」不是同一路径,但足以支撑系统侧轻量 UI 提示(仍须遵守多用户、显示层级等系统限制)。

4. 验证建议

  • 合并冲突 :ActivityStarter 在版本迭代中 diff 较多,建议基于同一 Android 12 基线打补丁并做 rebase 记录。
  • 日志 :保留 Slog.w(TAG, "ignore an intent: " + intent) 便于现场抓取完整 Intent,排查误杀。
  • 范围 :若仅针对「指定包名」拦截,可在上述判断外再增加 callingPackage / userid 等条件,避免影响系统组件或白名单应用。
相关推荐
朱涛的自习室1 小时前
我给 Gemini 4 和 DeepSeek 搞了套「末位淘汰」,AI 干活会更猛吗?(Day 3)
android·前端·后端
聚美智数3 小时前
网站HTTP状态查询-SEO优化
网络·网络协议·http
Frag0ut3 小时前
获取Chrome官方安装包:离线版安装风险避坑指南
chrome·google·谷歌浏览器·安装包·chromesetup.exe·在线安装包·离线版
云梦谭5 小时前
WebSocket 协议详解:从 HTTP 握手到全双工通信
websocket·网络协议·http
Initialize-le6 小时前
systemd 服务起不来?五步排查法
前端·chrome
应用市场7 小时前
离线小游戏做“每日挑战”:日期当随机种子,整局存成 JSON,再加一个“我不是机器人”
android·kotlin·游戏开发
一铭111998 小时前
海豹办公 1.9.15 跨端办公软件实践 文档兼容 Access 数据库与移动 WebView 排错
android·数据库·electron·开源软件·access
geats人山人海9 小时前
java 7异常
android·java·开发语言
2601_9620710010 小时前
Kimi K3 vs DeepSeek V4-Pro实测对比:2026年同一入口十道题,耗时与token消耗差在哪
android·java·数据库
右手吉他11 小时前
高通平台IA APN问题分析之二
android·物联网