解决换肤框架与高德地图的冲突

直接通过内存地址替换整个 ArtMethod ,完成了高德地图方法的替换。
This commit is contained in:
董宏宇
2020-12-29 18:44:01 +08:00
parent 347d7c5180
commit cab2517b1c
12 changed files with 628 additions and 15 deletions

View File

@@ -0,0 +1,67 @@
package com.mogo.module.common.hook;
import android.util.Pair;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 替换管理
* Created by donghongyu on 12/29/20 1:34 PM
*/
public final class HookManager {
private HookManager() {
}
public static HookManager get() {
return InstanceHolder.sInstance;
}
private static class InstanceHolder {
private static HookManager sInstance = new HookManager();
}
private Map<Pair<String, String>, MethodHook> methodHookMap = new ConcurrentHashMap<>();
/**
* 替换方法
*
* @param originMethod 原始方法
* @param hookMethod 替换方法
*/
public void hookMethod(Method originMethod, Method hookMethod) {
if (originMethod == null || hookMethod == null) {
throw new IllegalArgumentException("argument cannot be null");
}
Pair<String, String> key = Pair.create(hookMethod.getDeclaringClass().getName(), hookMethod.getName());
if (methodHookMap.containsKey(key)) {
MethodHook methodHook = methodHookMap.get(key);
methodHook.restore();
}
MethodHook methodHook = new MethodHook(originMethod, hookMethod);
methodHookMap.put(key, methodHook);
methodHook.hook();
}
public void callOrigin(Object receiver, Object... args) {
StackTraceElement stackTrace = Thread.currentThread().getStackTrace()[3];
String className = stackTrace.getClassName();
String methodName = stackTrace.getMethodName();
MethodHook methodHook = methodHookMap.get(Pair.create(className, methodName));
if (methodHook != null) {
try {
methodHook.callOrigin(receiver, args);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -0,0 +1,64 @@
package com.mogo.module.common.hook;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 替换类与c++代码对应
* Created by donghongyu on 12/29/20 1:34 PM
*/
public class MethodHook {
public static void m1() {
}
public static void m2() {
}
// 目标方法
private Method srcMethod;
// 要替换的方法
private Method hookMethod;
// 备份目标替换方法ID
private long backupMethodPtr;
public MethodHook(Method src, Method dest) {
srcMethod = src;
hookMethod = dest;
srcMethod.setAccessible(true);
hookMethod.setAccessible(true);
}
public void hook() {
if (backupMethodPtr == 0) {
backupMethodPtr = hook_native(srcMethod, hookMethod);
}
}
public void restore() {
if (backupMethodPtr != 0) {
restore_native(srcMethod, backupMethodPtr);
backupMethodPtr = 0;
}
}
public void callOrigin(Object receiver, Object... args) throws InvocationTargetException, IllegalAccessException {
if (backupMethodPtr != 0) {
restore();
srcMethod.invoke(receiver, args);
hook();
} else {
srcMethod.invoke(receiver, args);
}
}
private static native long hook_native(Method src, Method dest);
private static native Method restore_native(Method src, long methodPtr);
static {
System.loadLibrary("method-hook-lib");
}
}