文章目录

  • 理解IActivityController
  • 一 IActivityController.aidl简介
  • 二代码实现


理解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文件
  • 这一步需要编译源码获取去下载别人编译好的文件,最好版本要覆盖到当前使用api版本本文使用的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() + "======";
  • 通过反射设置代理类
//在进入页面时调用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();
        }
    }