IActivityController实现app启动监听

理解IActivityController

一 IActivityController.aidl简介

IActivityController.aidl是系统自带的aidl,在Am的内部类MyActivityController有实现这个aidl接口,主要用于app状态监听控制。对于应用开发者来说,此接口为给我们提供了各种可能性,比如统计每个app启动次数,crash次数等。这里我们先看下他的方法:

  • activityStarting:当系统正在启动一个activity时会触发,当返回true,表示允许启动。当返回状态noraml/false分别表示停止/拒绝启动activity
  • activityResuming:当系统正在返回一个activity时会触发,当返回true,表示允许返回。当返回状态noraml/false分别表示停止/拒绝返回activity
  • appCrashed:当一个应用进程已经崩溃会触发,当返回true时,表示可以重启,当返回false时,表示立即杀死它(进程)。
  • appEarlyNotResponding:检测到 ANR 时立即进行早期呼叫。
  • appNotResponding:当一个应用进程出现ANR时就会触发,当返回0时,表示会弹出应用无响应的dialog,如果返回1时,表示继续等待,如果返回-1时,表示立即杀死进程。
  • systemNotResponding:当系统看门狗已经监测到系统似乎挂起就会触发,如果放回1时,表示继续等待,如果返回-1时,就让系统进行正常的自杀(这里的正常自杀,我的理解是系统自己主动自杀,该保存的数据先保存等然后就自杀,并不是因为其他原因导致的自杀)

二代码实现

  • 生成framework.jar文件
  • 集成到工程
    • 把framework.jar文件放到工程libs文件中
    • 在工程build.gradle文件中添加
    • 在这里插入图片描述

    allprojects {
    repositories {
        google()
        jcenter()
    }
    gradle.projectsEvaluated {
        tasks.withType(JavaCompile) {
            try {
                def file = file('app\\libs\\frameworks.jar')
                println 'content==' + file.absolutePath
                options.compilerArgs.add('-Xbootclasspath/p:app\\libs\\frameworks.jar')

            } catch (FileNotFoundException e) {
                // nop, iml not found
                println "no iml found"
            }
        }
    }
* 在项目build.gradle中

    dependencies{
    //    Provided 的作用是只参与编译,但不打包到apk中
    compileOnly files('libs/framework.jar')
}
//同级添加  目的 framework.jar需要在jdk生效前设置,所以"dolast"的目的是把jdk加载置后
preBuild {
    doLast {
        //执行代码存在问题--路径问题-->是否跟modules中的app-->app.iml文件路径一至否则进入catch
        //.iml文件一般情况在.idea/modules/app中
        def imlFile = file(project.name + ".iml")
        println 'content==' + imlFile
        println 'Change ' + project.name + '.iml order'
        try {
            def parsedXml = (new XmlParser()).parse(imlFile)
            def jdkNode = parsedXml.component[1].orderEntry.find { it.'@type' == 'jdk' }
            parsedXml.component[1].remove(jdkNode)
            def sdkString = "Android API " + android.compileSdkVersion.substring("android-".length()) + " Platform"
            println 'what' + sdkString
            new Node(parsedXml.component[1], 'orderEntry', ['type': 'jdk', 'jdkName': sdkString, 'jdkType': 'Android SDK'])
            groovy.xml.XmlUtil.serialize(parsedXml, new FileOutputStream(imlFile))
        } catch (FileNotFoundException e) {
            println "no iml found"
        }
    }
}
[问题] 如果在项目中有其他jar文件 建议使用implementation files('libs/文件名.jar')
        否则在编译过程中会导致加载资源失败
  • 接下来需要新建一个代理类 继承IActivityController.Stub

    
          public class ActivityController extends IActivityController.Stub {
      private static final String TAG = ActivityController.class.getSimpleName() + "======";
    

    public boolean activityStarting(Intent intent, String pkg) throws RemoteException {
    //拦截动作
    Log.d(TAG, “>>>>>>start,pkg=” + pkg);
    return true;
    }
    public boolean activityResuming(String pkg) throws RemoteException {
    Log.d(TAG, “>>>>>>resuming,pkg=” + pkg);
    return false;
    }
    public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg, long timeMillis, String stackTrace) throws RemoteException {
    return false;
    }
    public int appEarlyNotResponding(String processName, int pid, String annotation) throws RemoteException {
    return 0;
    }
    public int appNotResponding(String processName, int pid, String processStats) throws RemoteException {
    return 0;
    }
    public int systemNotResponding(String msg) throws RemoteException {
    return 0;
    }
    }

  • 通过反射设置代理类


    //在进入页面时调用setActivityController()方法,注册aidl回调,当界面有变化时会触发activityStarting(),activityResuming()事件
    public void setActivityController() {
        Log.d(TAG, ">>>>>>0519,");
        try {
            Class<?> cActivityManagerNative = Class.forName("android.app.ActivityManagerNative");
//加载得到ServiceManager类,然后得到方法getService。
            Method getServiceMethod = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", new Class[]{String.class});
            //通过getServiceMethod得到ServiceManager的实例(隐藏类,所以使用Object)
            Object ServiceManager = getServiceMethod.invoke(null, new Object[]{"activity"});
            Method iBinder = cActivityManagerNative.getMethod("asInterface", IBinder.class);
            //获取到ActivityManagerService执行类
            Object iAMS = iBinder.invoke(null, ServiceManager);
            Method setMethod = iAMS.getClass().getMethod("setActivityController", Class.forName("android.app.IActivityController"), boolean.class);
            //用我们的代理类替换系统的代理
            setMethod.invoke(iAMS, new ActivityController(),true);
        } catch (ClassNotFoundException | NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

借鉴文章

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用中提到的组件生命周期和引用中提到的页面生命周期,我们可以得出结论:app启动页无法监听onBackPress。 onBackPress生命周期函数是在页面中监听用户点击返回按钮的事件,而启动页不属于页面,因此无法直接监听onBackPress事件。启动页的生命周期函数主要包括onLaunch、onShow和onHide,分别用于初始化完成、进入前台显示和进入后台隐藏时执行相应的操作。 如果您需要在启动页中实现类似的功能,可以考虑使用其他方法来监听返回按钮的点击事件,例如在app全局监听onBackPress事件,并在启动页中进行相应的处理。另外,在启动页中也可以使用其他生命周期函数或事件来实现您的需求,具体要根据您的具体情况来确定。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [uniapp 应用/页面/组件生命周期](https://blog.csdn.net/paidaboluo/article/details/126727393)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [uniapp APP端在线升级功能实现讲解——强制或可选升级,下载进度显示](https://blog.csdn.net/sd1sd2/article/details/131241609)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值