了解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.
