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


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

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

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

    adb shell dumpsys activity |findstr "mFocus"
    
    • 1

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

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

    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
        ActivityInfo aInfo = mTaskSupervisor.resolveActivity(intent, resolvedType,
                startFlags, profilerInfo, userId, Binder.getCallingUid());
        Log.d(TAG, "callingPackage = " + callingPackage);
        Log.d(TAG, "aInfo.taskAffinity = " + aInfo.taskAffinity);
        Log.d(TAG, "getCurrentApp() = " + getCurrentApp());
        if (GOOGLE_PACKAGE.equals(callingPackage) && GOOGLE_LOCATION_ACTIVITY.equals(aInfo.taskAffinity))) {
            Log.d(TAG, "Block Google location pop-ups");
            return ActivityManager.START_CANCELED;
        }
        // for disable google pop-up location alerts end
    
    
        userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
                Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
                
    //........省略多余代码.........
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

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

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

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

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

    system/frameworks/base/core/java/android/app/Dialog.java
    
    • 1
    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    那天,我听到了种子破土的声音,又细微又坚定。
  • 相关阅读:
    基于C语言编程的职工工资管理系统项目的设计与开发
    2019年Java面试题汇总
    基于Flask+Echarts的中药材价格分析与可视化项目
    【数据结构】二叉树的链式结构及实现
    前端面试基础题——12
    激活函数学习记录
    数据结构之——队列详解 ( 1 )
    甘特图组件DHTMLX Gantt示例 - 如何有效管理团队工作时间?(二)
    MMDetection自定义双主干Transformer模型(一)
    2022 China Collegiate Programming Contest (CCPC) Weihai Site A J
  • 原文地址:https://blog.csdn.net/weixin_45377770/article/details/138200688