加载回调接口,在xposed入口类继承,实现handleLoadPackage(XC_LoadPackage.LoadPackageParam)
,这个方法用于在打开app的时候回调,参数LoadPackageParam
包含了加载的应用程序的一些基本信息。
加载回调接口,用于修改app的资源文件,在xposed入口类继承,实现handleInitPackageResources(InitPackageResourcesParam)
方法,用于在加载应用程序的包的时候执行用户的操作 ,参数InitPackageResourcesParam
包含了加载的应用程序的一些资源基本信息。
加载回调接口,在xposed入口类继承,实现initZygote(IXposedHookZygoteInit.StartupParam)
,这个方法用于在开始hookApp的时候回调,参数StartupParam
包含了模块app的路径。
Xposed功能辅助类,里面提供了一些辅助方法,简化连接和调用方法/构造函数,获取和设置字段,这里直说重要的方法
findAndHookMethod: hook类中的某个方法
参数:
className: 要hook的方法的所在类
classloader: 要hook的包的classLoader,一般都写loadPackageParam.classLoader
methodName: 要hook的方法
parameterTypesAndCallback: 方法的参数和监听器。
callMethod: 在目标app中调用方法
参数:
Object: 要调用方法的所在类
methodName: 要调用的方法名称
args: 方法的参数
findClass: 获取class类实例
参数:
className: 类名
classLoader: 类加载器
Xposed 框架中真正起作用的是对方法的hook,hook到之后,在方法之前之后进行修改添加或者替换,那么寻找正确的目标方法名和所在的类名就很关键了。一般寻找目标方法有两种方法:
通过特定的类加载器加载要hook的类,通过反射找到被hook的成员。工具类XposedHelpers提供了一些工具方法来简化find过程;XposedBridge的hook*方法用于处理hook并执行回调。
XposedHelpers静态方法 | 描述 |
---|---|
findClass | 使用classLoader加载class |
findField | 通过反射查找类的数据成员并设置可访问性(setAccessible(true)) |
findMethod | 通过反射查找类的成员函数并设置可访问性 |
findConstructor | 通过反射查找类的构造函数并设置可访问性 |
setStatic | 通过反射设置类静态变量的值 |
set | 通过反射设置对象数据成员的值 |
findAndHook | 查找并hook |
XC_MethodHook中定义了回调方法:
@Override
protected final void beforeHookedMethod(MethodHookParam param) throws Throwable {
try {
Object result = replaceHookedMethod(param);
param.setResult(result);
} catch (Throwable t) {
param.setThrowable(t);
}
}
通过美元符号 $ 连接内部类, 例如:
//获取ItemDecoration的类路径
String clsName = "androidx.recyclerview.widget.RecyclerView$ItemDecoration"
只能hook正常的方法,或者实现的方法或者构造方法,不能hook接口和抽象方法
拿到之后可以用静态变量存放起来
try {
Class<?> ContextClass = findClass("android.content.ContextWrapper", loadPackageParam.classLoader);
findAndHookMethod(ContextClass, "getApplicationContext", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
Context applicationContext = (Context) param.getResult();
XposedBridge.log("得到上下文");
}
});
} catch (Throwable t) {
XposedBridge.log("获取上下文出错"+t);
}
例如获取一个EditText,上一篇文章的例子,获取TextView,修改字符。。打开被hook的app就会发现文本变成了"我是被Xposed修改的啦"
public class Main implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
findAndHookMethod("com.tpnet.companycalc.MainActivity",
loadPackageParam.classLoader,
"onCreate",
Bundle.class,
new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
//获取到当前hook的类,这里是MainActivity
Class clazz = param.thisObject.getClass();
XposedBridge.log("class name:" + clazz.getName());
// 输入框不为私有private 可通过以下方式获取
//Field field = clazz.getField("tvText");// 密码输入框对象变量名称
// 通过反射获取控件,无论parivate或者public
Field field = clazz.getDeclaredField("tvText");
// 设置访问权限
field.setAccessible(true);
TextView textView = (TextView) field.get(param.thisObject);
String string = textView.getText().toString();
XposedBridge.log("原来的字符 : " + string);
// 设置属性
textView.setText("我是被Xposed修改的啦");
}
}
);
}
}
通过反射获得得到自定义类
Class<?> hookMessageListenerClass = null;
hookMessageListenerClass = lpparam.classLoader.loadClass("org.jivesoftware.smack.MessageListener");
findAndHookMethod("org.jivesoftware.smack.ChatManager", lpparam.classLoader, "createChat", String.class , hookMessageListenerClass ,new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
String sendTo = (String) param.args[0];
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
}
});
XposedBridge类里面的findAndHookConstructor方法
Activity activity = (Activity) param.thisObject;
Intent intent = new Intent();
intent.setClassName(activity,"com.ushaqi.zhuishushenqi.ui.home.HomeActivity");
activity.startActivity(intent);
当你想调用宿主app里面的一个方法,方法的参数是一个接口,接口不能new的,这时候应该怎么办? 使用Proxy.newProxyInstance
/**
* 生成接口实例
* @param loader 类加载器
* @param interface 接口的Class实例
* @param h 接口回调
* /
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)