了解Android开发的同学可能听说过Xposed,它的强大可以说是只有你想不到的,没有它做不到的功能。 举个例子, 它可以修改系统的IMEI,手机号,甚至可以说可以让一台小米手机完全变成一台OPPO。
要知道Xposed是怎么做到的,首先要知道它的原理。 它是通过Hook API,替换掉原本的实现逻辑或者数据,来实现自己想要的方法。
看一段代码
XposedHelpers.findAndHookMethod(TelephonyManager.class.getName(), lpparam.classLoader, "getDeviceId", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("[afterHookedMethod] IMEI");
param.setResult("12345");
super.afterHookedMethod(param);
}
});
上面这段代码,把系统 TelephonyManager的 getDeviceId方法所返回的值,改成了 12345, 这样我们指定的 app调用 getDeviceId的话,就只能拿到 12345了。
实现很简单,我们只需要定义一个入口类,比如叫 MainHook.java,然后让它实现 IXposedHookLoadPackage接口就可以。
public class MainHook implements IXposedHookLoadPackage{
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
....
}
回调方法 handleLoadPackage会在系统每个app启动的时候回调一下,这时候就给了我们Hook的机会。 我们只需要判断 lpparam是否是我们的目标 app,就可以替换任何我们想要的方法。
一个完整的 Hook入口类demo差不多是这样的
public class MainHook implements IXposedHookLoadPackage{
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
if(!lpparam.packageName.equals("target.package")){
return;
}
XposedHelpers.findAndHookMethod(TelephonyManager.class.getName(), lpparam.classLoader, "getDeviceId", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("[afterHookedMethod] IMEI");
param.setResult("12345");
super.afterHookedMethod(param);
}
});
}
上面这个demo,就实现了Hook target.package 这个包名的app的 getDeviceId方法,从而返回我们设定的 12345.