Android 在AMS中拦截某个指定Activity的启动

Android在AMS中拦截某个具体Activity的启动

  最近在开发的过程中遇到这样一个问题,Android13项目带有GMS应用和服务的情况下,如果在系统中操作Location(位置信息),com.google.android.gms这个应用会弹出一个关于Location相关的提示框,因此非常影响我当下的业务需求和使用,所以我们研究如何屏蔽这个来自GMS的应用发出的弹窗。

  通过adb命令可以查询当前Activity的包名和具体Calss名

adb shell dumpsys activity |findstr "mFocus"

方案一(推荐):在ActivityTaskManagerService.startActivityAsUser方法中去作拦截

system/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

  AMS(ActivityManagerService)先校验一下Activity的正确性,如果正确的话,会暂存一下Activity的信息。然后,AMS会通知Launcher程序pause Activity(在AMS所在进程执行)

下面是AMS启动Activity的调用流程():

  • ActivityManagerService.startActivity

  • ActivityTaskManagerService.startActivity

  • ActivityTaskManagerService.startActivityAsUser(我是在这一步进行Activity的拦截的,因为这个方法中的参数比较明显,基本可以直接调用)

private final String GOOGLE_PACKAGE = "com.google.android.gms";
private final String GOOGLE_LOCATION_ACTIVITY = "com.google.android.gms.location.settings.LocationOffWarningActivity";

private int startActivityAsUser(IApplicationThread caller, String callingPackage,
        @Nullable String callingFeatureId, Intent intent, String resolvedType,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
    assertPackageMatchesCallingUid(callingPackage);
    enforceNotIsolatedCaller("startActivityAsUser");

	//........省略多余代码.........

    // for disable google pop-up location alerts begin
    try{
    ActivityInfo aInfo = mTaskSupervisor.resolveActivity(intent, resolvedType,
            startFlags, profilerInfo, userId, Binder.getCallingUid());
    Log.d(TAG, "callingPackage = " + callingPackage);
    //Log.d(TAG, "aInfo.taskAffinity = " + aInfo.taskAffinity);
    if (GOOGLE_PACKAGE.equals(callingPackage) && GOOGLE_LOCATION_ACTIVITY.equals(aInfo.taskAffinity))) {
        Log.d(TAG, "Block Google location pop-ups");
        return ActivityManager.START_CANCELED;
    }
    }catch(Exception e){
            Log.d(TAG, "e.getMessage = " + e.getMessage());
    }
    // for disable google pop-up location alerts end


    userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
            
	//........省略多余代码.........
}

方案二:在Dialog.show()方法中直接对这个包名所创建的Dialog做限制

  在上述第一个方案之前,我一开始遇到这个问题,脑海里直接想的是在Dialog.show()方法中里面去做拦截(因为弹窗本身就是一个Dialog)。我确实也尝试了,下面是我修改的代码。
但是后来我发现这样修改后,我思考了一下,会存在两个问题,例如:

  1.在Dialog中只能通过包名去拦截,不能直接拦截某一个指定的弹窗(或者说是Activity)。拦截一个和拦截这个包名中的全部来源,在本质上还是有区别的。

  2.虽然这种方式可以达到拦截Dialog弹窗的目的,但是依旧还是会走Activity的创建流程。既然弹窗都屏蔽掉了,那这样会有什么影响呢?
因为我项目中的业务是在某个应用的使用过程中不想要出现这个提示框,那么我就要获取到当前顶层运行的应用和Activity,实际获取到的还是这个弹窗的包名和Activity,因为虽然屏蔽掉了Dialog,但是它依然走的是Activity的启动流程,所以这种方式并不周全。

system/frameworks/base/core/java/android/app/Dialog.java
private final String GOOGLE_PACKAGE = "com.google.android.gms";

public void show() {
	//........省略多余代码.........
	
    onStart();
    mDecor = mWindow.getDecorView();

    // for disable google pop-up location alerts begin
    Log.d(TAG, "mContext.getPackageName() = " + mContext.getPackageName());
    if(GOOGLE_PACKAGE_NAME.equals(mContext.getPackageName())) { 
        Log.d(TAG, "Disable Google location pop-ups");
        return;
    }
    // for disable google pop-up location alerts end
    
    if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
        final ApplicationInfo info = mContext.getApplicationInfo();
        mWindow.setDefaultIcon(info.icon);
        mWindow.setDefaultLogo(info.logo);
        mActionBar = new WindowDecorActionBar(this);
    }
    
    //........省略多余代码.........
那天,我听到了种子破土的声音,又细微又坚定。

相关推荐

  1. Android AMS拦截某个指定Activity启动

    2024-04-29 16:56:05       31 阅读
  2. Android11 后台启动Activity

    2024-04-29 16:56:05       31 阅读
  3. android Activity onCreate 获取View 宽高

    2024-04-29 16:56:05       21 阅读
  4. 如何指定conda虚拟环境启动Juptyter

    2024-04-29 16:56:05       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-29 16:56:05       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-29 16:56:05       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-29 16:56:05       82 阅读
  4. Python语言-面向对象

    2024-04-29 16:56:05       91 阅读

热门阅读

  1. CMUS狮身人面像(七)-Android 上的 PocketSphinx

    2024-04-29 16:56:05       37 阅读
  2. golang变量常见问题总结

    2024-04-29 16:56:05       31 阅读
  3. go圣经 ——方法

    2024-04-29 16:56:05       38 阅读
  4. 【AI大模型】Prompt Engineering 基础知识与挑战

    2024-04-29 16:56:05       35 阅读
  5. 【Spring AI】03. 图像生成 API

    2024-04-29 16:56:05       31 阅读
  6. git版本控制基础工作流

    2024-04-29 16:56:05       31 阅读
  7. k8s的PV/PVC详解以及使用范例

    2024-04-29 16:56:05       28 阅读
  8. Android面试

    2024-04-29 16:56:05       32 阅读
  9. 从零开始搭建SpringCloud

    2024-04-29 16:56:05       31 阅读
  10. react怎么只让接口请求一次

    2024-04-29 16:56:05       31 阅读
  11. P9586 「MXOI Round 2」游戏

    2024-04-29 16:56:05       32 阅读