Merge branch 'qa_merge_shunyi_vr_map' into dev_1.1.9
This commit is contained in:
102
modules/mogo-module-common/src/main/cpp/method-hook-lib.cpp
Normal file
102
modules/mogo-module-common/src/main/cpp/method-hook-lib.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
#include <jni.h>
|
||||
#include <string.h>
|
||||
|
||||
//
|
||||
// Created by donghongyu on 12/10/20 1:34 PM.
|
||||
// 源码地址 https://github.com/pqpo/methodhook
|
||||
// 方法hook jni类
|
||||
static const char *kClassMethodHookChar = "com/mogo/module/common/hook/MethodHook";
|
||||
|
||||
static struct {
|
||||
jmethodID m1;
|
||||
jmethodID m2;
|
||||
size_t methodSize;
|
||||
} methodHookClassInfo;
|
||||
|
||||
|
||||
/**
|
||||
* 替换指定类中的方法
|
||||
* @param env
|
||||
* @param type
|
||||
* @param srcMethodObj 目标方法对象
|
||||
* @param destMethodObj 替换的方法对象
|
||||
* @return
|
||||
*/
|
||||
static jlong methodHook(JNIEnv *env, jclass type, jobject srcMethodObj, jobject destMethodObj) {
|
||||
// 反射:获取了Java对象的在native层的 ArtMethod指针
|
||||
void *srcMethod = reinterpret_cast<void *>(env->FromReflectedMethod(srcMethodObj));
|
||||
void *destMethod = reinterpret_cast<void *>(env->FromReflectedMethod(destMethodObj));
|
||||
// 定义存储方法ID的数组
|
||||
int *backupMethod = new int[methodHookClassInfo.methodSize];
|
||||
// 使用的内存拷贝函数
|
||||
// 将旧方法ID拷贝到数组中
|
||||
memcpy(backupMethod, srcMethod, methodHookClassInfo.methodSize);
|
||||
// 将新方法替换到旧方法地址上
|
||||
memcpy(srcMethod, destMethod, methodHookClassInfo.methodSize);
|
||||
// 将旧方法ID返回给java层,用来做方法还原使用
|
||||
return reinterpret_cast<long>(backupMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
* 恢复指定类中的方法
|
||||
* @param env
|
||||
* @param type
|
||||
* @param srcMethod 目标方法对象
|
||||
* @param methodPtr
|
||||
* @return
|
||||
*/
|
||||
static jobject methodRestore(JNIEnv *env, jclass type, jobject srcMethod, jlong methodPtr) {
|
||||
// 要还原的旧方法 指针
|
||||
int *backupMethod = reinterpret_cast<int *>(methodPtr);
|
||||
// 获取了Java对象的在native层的 ArtMethod指针
|
||||
void *artMethodSrc = reinterpret_cast<void *>(env->FromReflectedMethod(srcMethod));
|
||||
// 将旧方法指针,替换到 artMethodSrc 中
|
||||
memcpy(artMethodSrc, backupMethod, methodHookClassInfo.methodSize);
|
||||
// 删除旧方法备份指针
|
||||
delete[]backupMethod;
|
||||
// 返回旧方法
|
||||
return srcMethod;
|
||||
}
|
||||
|
||||
// 定义要注册的方法
|
||||
static JNINativeMethod gMethods[] = {
|
||||
{
|
||||
"hook_native",
|
||||
"(Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;)J",
|
||||
(void *) methodHook
|
||||
},
|
||||
{
|
||||
"restore_native",
|
||||
"(Ljava/lang/reflect/Method;J)Ljava/lang/reflect/Method;",
|
||||
(void *) methodRestore
|
||||
}
|
||||
};
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
/**
|
||||
* 在jni加载的时候进行方法参数获取
|
||||
* @param vm
|
||||
* @param reserved
|
||||
* @return
|
||||
*/
|
||||
JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
JNIEnv *env = nullptr;
|
||||
if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
// 加载指定java class
|
||||
jclass classEvaluateUtil = env->FindClass(kClassMethodHookChar);
|
||||
// 注册
|
||||
if (env->RegisterNatives(classEvaluateUtil, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) <
|
||||
0) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
// 获取 MethodHook m1、m2 的方法ID
|
||||
methodHookClassInfo.m1 = env->GetStaticMethodID(classEvaluateUtil, "m1", "()V");
|
||||
methodHookClassInfo.m2 = env->GetStaticMethodID(classEvaluateUtil, "m2", "()V");
|
||||
// 获取artMethod的大小,
|
||||
methodHookClassInfo.methodSize = reinterpret_cast<size_t>(methodHookClassInfo.m2) -
|
||||
reinterpret_cast<size_t>(methodHookClassInfo.m1);
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
@@ -73,11 +73,27 @@ public class BezierAnimationView extends RelativeLayout implements View.OnClickL
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
public void bezierAnimationStart(){
|
||||
runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Log.d("点赞--", "");
|
||||
bezierAnimation(resource);
|
||||
handler.postDelayed(this, 500);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
private void bezierAnimation(int resource) {
|
||||
final ImageView imageView = new ImageView(context);
|
||||
imageView.setBackgroundResource(animation_drawable[resource]);
|
||||
RelativeLayout.LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
params.addRule(ALIGN_BOTTOM);
|
||||
// params.addRule(ALIGN_BOTTOM);
|
||||
params.addRule(CENTER_HORIZONTAL);
|
||||
imageView.setLayoutParams(params);
|
||||
addView(imageView);
|
||||
|
||||
@@ -50,10 +50,10 @@ public class MapMarkerAdapter {
|
||||
* @return MarkerView
|
||||
*/
|
||||
public static IMarkerView getMarkerInfoWindowView( Context context, MarkerShowEntity markerShowEntity, MogoMarkerOptions options ) {
|
||||
if ( markerShowEntity.isChecked() ) {
|
||||
return new MapMarkerInfoView( context, markerShowEntity, options );
|
||||
} else {
|
||||
return new MapMarkerView( context, markerShowEntity, options );
|
||||
}
|
||||
// if ( markerShowEntity.isChecked() ) {
|
||||
// return new MapMarkerInfoView( context, markerShowEntity, options );
|
||||
// } else {
|
||||
// }
|
||||
return new MapMarkerView( context, markerShowEntity, options );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,11 @@ public class MapMarkerInfoView extends MapMarkerBaseView {
|
||||
public MapMarkerInfoView( Context context, MarkerShowEntity markerShowEntity, MogoMarkerOptions options ) {
|
||||
super( context );
|
||||
mOptions = options;
|
||||
updateView( markerShowEntity );
|
||||
try {
|
||||
updateView( markerShowEntity );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,7 +64,7 @@ public class MapMarkerInfoView extends MapMarkerBaseView {
|
||||
LayoutInflater.from( context ).inflate( R.layout.modudle_services_marker_layout_info, this );
|
||||
ivUserHead = findViewById( R.id.ivUserHead );
|
||||
// ivIcon = findViewById( R.id.ivIcon );
|
||||
ivIcon = findViewById(R.id.ivIcon);
|
||||
ivIcon = findViewById( R.id.ivIcon );
|
||||
clMarkerContent = findViewById( R.id.clMarkerContent );
|
||||
ivReverseTriangle = findViewById( R.id.ivReverseTriangle );
|
||||
ivCar = findViewById( R.id.ivCar );
|
||||
@@ -69,84 +73,80 @@ public class MapMarkerInfoView extends MapMarkerBaseView {
|
||||
|
||||
@Override
|
||||
public void updateView( MarkerShowEntity markerShowEntity ) {
|
||||
try {
|
||||
|
||||
Object bindObj = markerShowEntity.getBindObj();
|
||||
Object bindObj = markerShowEntity.getBindObj();
|
||||
|
||||
if ( MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode() ) {
|
||||
ivCar.setImageResource( R.drawable.icon_map_marker_location_yellow_vr );
|
||||
} else {
|
||||
ivCar.setImageResource( R.drawable.icon_map_marker_location_yellow );
|
||||
}
|
||||
clMarkerContent.setBackgroundResource( R.drawable.bg_map_marker_yellow_info );
|
||||
ivReverseTriangle.setImageResource( R.drawable.bg_shape_reverse_yellow );
|
||||
switch ( markerShowEntity.getMarkerType() ) {
|
||||
case ModuleNames.CARD_TYPE_CARS_CHATTING:
|
||||
case ModuleNames.CARD_TYPE_USER_DATA:
|
||||
ivUserHead.setVisibility( View.VISIBLE );
|
||||
ivIcon.setVisibility( View.INVISIBLE );
|
||||
loadImageWithMarker( markerShowEntity );
|
||||
ivCar.setImageResource( R.drawable.icon_map_marker_car_gray );
|
||||
//ivCar.setRotation(new Random().nextInt(360));
|
||||
ivCar.setRotation( ( float ) markerShowEntity.getMarkerLocation().getAngle() );
|
||||
break;
|
||||
case ModuleNames.CARD_TYPE_ROAD_CONDITION:
|
||||
case ModuleNames.CARD_TYPE_NOVELTY:
|
||||
ivUserHead.setVisibility( View.INVISIBLE );
|
||||
ivIcon.setVisibility( View.VISIBLE );
|
||||
|
||||
if ( bindObj instanceof MarkerExploreWay && ( ( MarkerExploreWay ) bindObj ).getPoiType() != null ) {
|
||||
// 根据poiType获取对应的图片
|
||||
String poiType = ((MarkerExploreWay) bindObj).getPoiType();
|
||||
PoiWrapper poiWrapper =
|
||||
CloudPoiManager.getInstance().getWrapperByPoiType(poiType);
|
||||
if (poiWrapper != null) {
|
||||
// 加载图片
|
||||
loadPoiTypeIcon(poiWrapper.getIconInfoUrl(),poiWrapper.getIconInfoRes());
|
||||
}else{
|
||||
Logger.e(TAG, "未能根据poiType获取对应poi信息,无法渲染info marker====" + poiType);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ModuleNames.CARD_TYPE_SHARE_MUSIC:
|
||||
ivUserHead.setVisibility( View.INVISIBLE );
|
||||
ivIcon.setVisibility( View.VISIBLE );
|
||||
|
||||
if ( bindObj instanceof MarkerShareMusic ) {
|
||||
// 2 为书籍听书,3 为新闻,1 为qq音乐,int
|
||||
switch ( ( ( MarkerShareMusic ) bindObj ).getShareType() ) {
|
||||
case 1:
|
||||
ivIcon.setImageResource( R.drawable.icon_map_marker_misic );
|
||||
break;
|
||||
case 2:
|
||||
ivIcon.setImageResource( R.drawable.icon_map_marker_book );
|
||||
break;
|
||||
case 3:
|
||||
ivIcon.setImageResource( R.drawable.icon_map_marker_news );
|
||||
break;
|
||||
default:
|
||||
ivIcon.setImageResource( R.drawable.icon_map_marker_misic );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ( !TextUtils.isEmpty( markerShowEntity.getTextContent() ) ) {
|
||||
String content;
|
||||
if ( markerShowEntity.getTextContent().length() > 8 ) {
|
||||
content = markerShowEntity.getTextContent().substring( 0, 7 ) + "...";
|
||||
} else {
|
||||
content = markerShowEntity.getTextContent();
|
||||
}
|
||||
tvMarkerContent.setText( content );
|
||||
}
|
||||
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
if ( MogoApisHandler.getInstance().getApis().getStatusManagerApi().isVrMode() ) {
|
||||
ivCar.setImageResource( R.drawable.icon_map_marker_location_yellow_vr );
|
||||
} else {
|
||||
ivCar.setImageResource( R.drawable.icon_map_marker_location_yellow );
|
||||
}
|
||||
clMarkerContent.setBackgroundResource( R.drawable.bg_map_marker_yellow_info );
|
||||
ivReverseTriangle.setImageResource( R.drawable.bg_shape_reverse_yellow );
|
||||
switch ( markerShowEntity.getMarkerType() ) {
|
||||
case ModuleNames.CARD_TYPE_CARS_CHATTING:
|
||||
case ModuleNames.CARD_TYPE_USER_DATA:
|
||||
ivUserHead.setVisibility( View.VISIBLE );
|
||||
ivIcon.setVisibility( View.INVISIBLE );
|
||||
loadImageWithMarker( markerShowEntity );
|
||||
ivCar.setImageResource( R.drawable.icon_map_marker_car_gray );
|
||||
//ivCar.setRotation(new Random().nextInt(360));
|
||||
ivCar.setRotation( ( float ) markerShowEntity.getMarkerLocation().getAngle() );
|
||||
break;
|
||||
case ModuleNames.CARD_TYPE_ROAD_CONDITION:
|
||||
case ModuleNames.CARD_TYPE_NOVELTY:
|
||||
ivUserHead.setVisibility( View.INVISIBLE );
|
||||
ivIcon.setVisibility( View.VISIBLE );
|
||||
|
||||
if ( bindObj instanceof MarkerExploreWay && ( ( MarkerExploreWay ) bindObj ).getPoiType() != null ) {
|
||||
// 根据poiType获取对应的图片
|
||||
String poiType = ( ( MarkerExploreWay ) bindObj ).getPoiType();
|
||||
PoiWrapper poiWrapper =
|
||||
CloudPoiManager.getInstance().getWrapperByPoiType( poiType );
|
||||
if ( poiWrapper != null ) {
|
||||
// 加载图片
|
||||
loadPoiTypeIcon( poiWrapper.getIconInfoUrl(), poiWrapper.getIconInfoRes() );
|
||||
} else {
|
||||
Logger.e( TAG, "未能根据poiType获取对应poi信息,无法渲染info marker====" + poiType );
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ModuleNames.CARD_TYPE_SHARE_MUSIC:
|
||||
ivUserHead.setVisibility( View.INVISIBLE );
|
||||
ivIcon.setVisibility( View.VISIBLE );
|
||||
|
||||
if ( bindObj instanceof MarkerShareMusic ) {
|
||||
// 2 为书籍听书,3 为新闻,1 为qq音乐,int
|
||||
switch ( ( ( MarkerShareMusic ) bindObj ).getShareType() ) {
|
||||
case 1:
|
||||
ivIcon.setImageResource( R.drawable.icon_map_marker_misic );
|
||||
break;
|
||||
case 2:
|
||||
ivIcon.setImageResource( R.drawable.icon_map_marker_book );
|
||||
break;
|
||||
case 3:
|
||||
ivIcon.setImageResource( R.drawable.icon_map_marker_news );
|
||||
break;
|
||||
default:
|
||||
ivIcon.setImageResource( R.drawable.icon_map_marker_misic );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if ( !TextUtils.isEmpty( markerShowEntity.getTextContent() ) ) {
|
||||
String content;
|
||||
if ( markerShowEntity.getTextContent().length() > 8 ) {
|
||||
content = markerShowEntity.getTextContent().substring( 0, 7 ) + "...";
|
||||
} else {
|
||||
content = markerShowEntity.getTextContent();
|
||||
}
|
||||
tvMarkerContent.setText( content );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ import com.mogo.utils.logger.Logger;
|
||||
* desc : 地图Marker图标
|
||||
* version: 1.0
|
||||
*/
|
||||
public class
|
||||
MapMarkerView extends MapMarkerBaseView {
|
||||
public class MapMarkerView extends MapMarkerBaseView {
|
||||
private String TAG = "MapMarkerView";
|
||||
|
||||
private FrameLayout clMarkerTopView;
|
||||
private MarkerShowEntity mMarkerShowEntity;
|
||||
|
||||
public MapMarkerView( Context context ) {
|
||||
super( context );
|
||||
@@ -45,7 +45,12 @@ MapMarkerView extends MapMarkerBaseView {
|
||||
public MapMarkerView( Context context, MarkerShowEntity markerShowEntity, MogoMarkerOptions options ) {
|
||||
super( context );
|
||||
mOptions = options;
|
||||
updateView( markerShowEntity );
|
||||
mMarkerShowEntity = markerShowEntity;
|
||||
try {
|
||||
updateView( markerShowEntity );
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,37 +60,35 @@ MapMarkerView extends MapMarkerBaseView {
|
||||
} else {
|
||||
LayoutInflater.from( context ).inflate( R.layout.modudle_services_marker_layout, this );
|
||||
}
|
||||
ivIcon = findViewById( R.id.ivIcon );
|
||||
clMarkerTopView = findViewById( R.id.clMarkerTopView );
|
||||
ivIcon = findViewById( R.id.ivIcon );
|
||||
ivCar = findViewById( R.id.ivCar );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateView( MarkerShowEntity markerShowEntity ) {
|
||||
try {
|
||||
Object bindObj = markerShowEntity.getBindObj();
|
||||
switch ( markerShowEntity.getMarkerType() ) {
|
||||
case ModuleNames.CARD_TYPE_ROAD_CONDITION:
|
||||
case ModuleNames.CARD_TYPE_NOVELTY:
|
||||
if ( bindObj instanceof MarkerExploreWay && ( ( MarkerExploreWay ) bindObj ).getPoiType() != null ) {
|
||||
// 根据poiType获取对应的图片
|
||||
String poiType = ( ( MarkerExploreWay ) bindObj ).getPoiType();
|
||||
PoiWrapper poiWrapper =
|
||||
CloudPoiManager.getInstance().getWrapperByPoiType( poiType );
|
||||
if ( poiWrapper != null ) {
|
||||
// 加载图片
|
||||
loadPoiTypeIcon( poiWrapper.getIconUrl(), poiWrapper.getIconRes() );
|
||||
} else {
|
||||
Logger.e( TAG, "未能根据poiType获取对应poi信息,无法渲染marker====" + poiType );
|
||||
}
|
||||
Object bindObj = markerShowEntity.getBindObj();
|
||||
switch ( markerShowEntity.getMarkerType() ) {
|
||||
case ModuleNames.CARD_TYPE_ROAD_CONDITION:
|
||||
case ModuleNames.CARD_TYPE_NOVELTY:
|
||||
if ( mMarkerShowEntity != null && mMarkerShowEntity.isChecked() ) {
|
||||
clMarkerTopView.setBackgroundResource( R.drawable.module_services_marker_vr_bkg_checked );
|
||||
}
|
||||
if ( bindObj instanceof MarkerExploreWay && ( ( MarkerExploreWay ) bindObj ).getPoiType() != null ) {
|
||||
// 根据poiType获取对应的图片
|
||||
String poiType = ( ( MarkerExploreWay ) bindObj ).getPoiType();
|
||||
PoiWrapper poiWrapper =
|
||||
CloudPoiManager.getInstance().getWrapperByPoiType( poiType );
|
||||
if ( poiWrapper != null ) {
|
||||
// 加载图片
|
||||
loadPoiTypeIcon( poiWrapper.getIconUrl(), poiWrapper.getIconRes() );
|
||||
} else {
|
||||
Logger.e( TAG, "未能根据poiType获取对应poi信息,无法渲染marker====" + poiType );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
} catch ( Exception e ) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* hook方法
|
||||
*
|
||||
* @param src 要替换的方法对象
|
||||
* @param dest 被替换的方法对象
|
||||
*/
|
||||
public MethodHook(Method src, Method dest) {
|
||||
srcMethod = src;
|
||||
hookMethod = dest;
|
||||
srcMethod.setAccessible(true);
|
||||
hookMethod.setAccessible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用 native 层,完成替换
|
||||
*/
|
||||
public void hook() {
|
||||
if (backupMethodPtr == 0) {
|
||||
backupMethodPtr = hook_native(srcMethod, hookMethod);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用 native 层,完成方法还原
|
||||
*/
|
||||
public void restore() {
|
||||
if (backupMethodPtr != 0) {
|
||||
restore_native(srcMethod, backupMethodPtr);
|
||||
backupMethodPtr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用原来class 对象中的方法
|
||||
*
|
||||
* @param receiver 接受对象
|
||||
* @param args 方法列表
|
||||
* @throws InvocationTargetException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public void callOrigin(Object receiver, Object... args)
|
||||
throws InvocationTargetException, IllegalAccessException {
|
||||
if (backupMethodPtr != 0) {
|
||||
restore();
|
||||
srcMethod.invoke(receiver, args);
|
||||
hook();
|
||||
} else {
|
||||
srcMethod.invoke(receiver, args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用 native 方法完成 方法替换
|
||||
*
|
||||
* @param src 旧方法
|
||||
* @param dest 新方法
|
||||
* @return 就方法ID
|
||||
*/
|
||||
private static native long hook_native(Method src, Method dest);
|
||||
|
||||
/**
|
||||
* 调用 native 方法完成 方法还原
|
||||
*
|
||||
* @param src
|
||||
* @param methodPtr
|
||||
* @return
|
||||
*/
|
||||
private static native Method restore_native(Method src, long methodPtr);
|
||||
|
||||
static {
|
||||
// 加载本地方法 so
|
||||
System.loadLibrary("method-hook-lib");
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#890">
|
||||
|
||||
<com.mogo.module.common.animation.BezierAnimationView
|
||||
android:id="@+id/bezier_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#7810" />
|
||||
|
||||
</RelativeLayout>
|
||||
Reference in New Issue
Block a user