文章目录
- 理解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();
}
}