android监听app启动
有时候你会遇到一些比较`邪恶`的需求,比如某些游戏加速软件,在游戏开始运行的时候,执行以下内存清理。这个就需要监听游戏的启动了。如何实现这个需求呢?

前言
有时候你会遇到一些比较邪恶
的需求,比如某些游戏加速软件,在游戏开始运行的时候,执行以下内存清理。这个就需要监听游戏的启动了。如何实现这个需求呢?
原理
在android.app.ActivityManagerNative类里面定义了一个setActivityController(IActivityController watcher)方法,该方法通过参数IAcitivityController设置一个监听器,用来监听系统启动某个Activity。当系统启动某个Activity时,会调用IAcitivityController的回调方法。
在工程中可以通过获取ActivityManagerNative对象并生成一个IActivityController实例作为setActivityController()的参数传递过去,从而达到在工程中监听到系统Activity的启动。
既然如此,那还不简单,直接调用方法就可以了,但是。现实是残酷的。因为这个方法是隐藏方法。
package android.app;
/** {@hide} */
public abstract class ActivityManagerNative extends Binder implements IActivityManager{
/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
public void setActivityController(IActivityController watcher) throws RemoteException{}
}
package android.app;
import android.content.Intent;
/**
* Testing interface to monitor what is happening in the activity manager
* while tests are running. Not for normal application development.
* {@hide}
*/
interface IActivityController
可以看到,都有hide
标签。因此在api里面是找不到这个方法的。也找不到IActivityController
这个接口。怎么办?
解决方案
方法一
从手机里面提取framework.jar。将android.app.ActivityManagerNative.class和其内部类都提取出来,将android.app.IActivityController和其内部类都提取出来。替换掉当前开发环境中的sdk的platform的android.jar里面相应的class。刷新一下工程,就可以调用这两个隐藏的内容了。
方法二
如果觉得方法一太复杂了,则可以使用反射来调用隐藏方法。此处摘自pierce0young的专栏
解决方案:把系统内的IActivityController.aidl文件在我们自己的工程里按照同样的包结构创建一份,在程序中继承该接口,在调用setActivityController时传入该实例即可。
1、拷贝系统内IActivityController.aidl到工程中,与系统内该文件包结构保持一致:
这里提供一下aidl的传送门
2、程序中实现该接口:
private class ActivityController extends IActivityController.Stub {
public boolean activityStarting(Intent intent, String pkg) {
return true;
}
public boolean activityResuming(String pkg) {
return true;
}
public int appEarlyNotResponding(String processName, int pid,
String annotation) {
return 0;
}
public boolean appCrashed(String processName, int pid, String shortMsg,
String longMsg, long timeMillis, String stackTrace) {
return false;
}
public int appNotResponding(String processName, int pid,
String processStats) {
return 0;
}
}
3、通过反射获取ActivityManagerNative对象并调用方法setActivityController进行监听器设置:
private void setActivityController() {
try {
Class<?> cActivityManagerNative = Class
.forName("android.app.ActivityManagerNative");
Method mGetDefault = cActivityManagerNative.getMethod("getDefault",
null);
Object oActivityManagerNative = mGetDefault.invoke(null, null);
Class<?> i = Class.forName("android.app.IActivityController$Stub");
Method mSetActivityController = cActivityManagerNative.getMethod(
"setActivityController",
Class.forName("android.app.IActivityController"));
mSetActivityController.invoke(oActivityManagerNative,
new ActivityController());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
至此。就实现了监听任意app启动了。当任意app启动时都会触发activityStarting
方法。在这个方法里面写上你的逻辑处理即可。如果你想中断此app的启动:
public boolean activityStarting(Intent intent, String pkg) {
return false;//即可中断app启动
}
其他几个回调方法请自行发掘,这里就不多讲述了。