一.原理
android每打开一个 app,zygote 进程 fork(进程复用)出一个虚拟机来运行 app,xposed 就是通过改造 zygote来实现对 app_progress的替换
二.安装 xposed 支持
1.版本 Xposed Installer
2.版本 EdXposed (支持高版本:https://repo.xposed.info/module/org.meowcat.edxposed.manager)
三.编写步骤
1.新建项目
2.更改 AndroidMainfest.xml ,在 application 标签内部添加如下配置:
<!--添加 module-->
<meta-data
android:name="xposedmodule"
android:value="true"
/>
<!--添加 描述-->
<meta-data
android:name="xposeddescription"
android:value="xposedHookPorject"
/>
<!--添加 jar 版本 -->
<meta-data
android:name="xposedminversion"
android:value="54"
/>
3.在 app 目录下新建 lib,导入 xposedBridge.jar(xposed 的开发 api的 jar)
或者:在 build.gradle 引入:compileOnly ‘de.robv.android.xposed:api:82’
4.新建程序入口类 HookTest 实现自 IXposedHoodLoadPackage
5.新建 xposed程序入口配置文件 xposed_init(名字固定),内容为:包名+入口名
四.避免修改 hook 后重启 (没有试过,网上有方案,原理如下)
1.重启方式,性能优、每次需要重启,直接加载IXposedHookLoadPackage中的 handleLoadPackage
2.避免重启,遍历 data/app下的apk并加载,损耗性能,采用加载中间IXposedHookLoadPackage类然后加载 apk文件,再调用实际需要 hook 的IXposedHookLoadPackage,每次修改 hook 之后,需要重启中间IXposedHookLoadPackage程序
五.常用的 hook api
1.hook 方法参数 -> findAndHookMethod
XposedHelpers.findAndHookMethod(包名+类名,
param.classLoader,
"",//方法名
String.class,String.class,//参数
new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
XposedBridge.log("第一个参数:" + param.args[0]);
XposedBridge.log("第二个参数:" + param.args[1]);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
param.setResult("Hook succeed");
XposedBridge.log("返回值:" + param.getResult());
param.setResult(true);
}
});
2.主动调用类中的方法 -> callMethod(普通方法)/callStaticMethod(静态方法)
String result = XposedHelpers.callStaticMethod(loadPackageParam.getClass(), "方法名", new Object[]{""});
3.调用字段属性方法等
Class<?> clazz = param.thisObject.getClass();//获取类
Field field = clazz.getDeclaredField(字段名);//通过字段名字获取属性
field.setAccessible(true);//设置对外可见
Object obj = (Object) field.get(param.thisObject);
Method method = clazz.getDeclaredMethod(方法名,new Class[]{byte[].class,String.class});//获取方法
method.setAccessible(true);//方法可见
String resultStr = (String) method.invoke(param.thisObject,参数 1, 参数 2,....);
4.多 dex 情况下hook
方案 1:遍历所有的类,进行匹配
方案 2:通过参数获取当前程序的类加载器Application.class,通过获取到的类加载器,再 hook 方法或字段
## 五.坑
1.Xposed Installer 打开后提示,模块加载失败
解决:直接更新
2.Xposed Installer 里面没有模块
解决:工程 xposed_init入口和 AndroidManifest.xml 配置是否正确
3.模块加载进来,hook 所有日志不打印(太惨了~ ~)
解决:在 Xposed Installer模块中,重新开关模块之后重启设备