Java回调函数与什么是hook
Java回调函数Demo:
public class HookUtil { private static HookUtil hookUtil ; private HookUtil(){} public static HookUtil getInstance(){ if(hookUtil == null){ hookUtil = new HookUtil(); } return hookUtil; } public interface HookUtilCallback{ void backSuccess(int code); void backFail(int code); } private HookUtilCallback hookUtilCallback = null; public void setHookUtilCallback(HookUtilCallback callback){ hookUtilCallback = callback; } public void doSomething(int code){ if(hookUtilCallback != null){ hookUtilCallback.backFail(code); } } }
public class DemoT1 {
//控件监听回调 --简单版
public demoT1_ClickListener mDemoT1_clickListener;
public interface demoT1_ClickListener {
void T1Click();
}
public void setDemoT1_clickListener(demoT1_ClickListener demoT1_clickListener){
demoT1_clickListener = mDemoT1_clickListener;
}
//回调函数--demo版
private interface Response {
void onSuccess(String data);
void onFailed(String prompt);
}
private static String doSomething(){
try {
//......
Thread.sleep(5000); //模拟耗时操作(如网络请求),操作正常返回"Success","Success"表示有效的数据
return "Success";
} catch (InterruptedException ex) {
Logger.getLogger(DemoT1.class.getName()).log(Level.SEVERE, null, ex);
//操作出现问题返回"Failed","Failed"包含错误提示,如错误码等
return "Failed";
}
}
// 使用回调函数操作
private static void callbackDoSomething(Response response){
try {
Thread.sleep(5000);
response.onSuccess("Success");
} catch (InterruptedException ex) {
Logger.getLogger(DemoT1.class.getName()).log(Level.SEVERE, null, ex);
response.onFailed("Failed");
}
}
public static void main(String[] args) {
//实例
DemoT1.callbackDoSomething(new Response() {
@Override
public void onSuccess(String data) {
}
@Override
public void onFailed(String prompt) {
}
});
}
}
HOOK:什么是hook?
hook (钩子) -->在java中它表示在事件到达终点前进行拦截或监控的一种行为.
/**
*实现hook我们必须要知道java的反射和动态代理
*/
public class HookDemo {
/**
* 反射是java的查看、检测、修改自身的一种行为。
*在编译阶段,编译器将我们编写的java文件编译成.class文件。
* 而在运行期,jvm又将.class文件通过类加载器ClassLoader加载一个类对应的Class对象到内存当中。
* 通过修改Class对象,达到我们查看、检测、修改自身的行为。
*/
Class mClass;
{
try {
/*
* Constructor constructor = mClass.getConstructor(); 拿到构造函数
* DemoT1 t1 = (DemoT1) constructor.newInstance(DemoT1.class);获取新实例
*
* 同理,通过class类对象,可以获取对象的方法。动态代理中需要在方法拦截。
Methods method[] = mClass.getDeclaredMethods();
*
获取对象的域,
Field[] fields = mClass.getDeclaredFields();
*
* */
mClass = Class.forName("com.android.myapplication.demo1.DemoT1");
Constructor constructor = mClass.getConstructor();
DemoT1 t1 = (DemoT1) constructor.newInstance(DemoT1.class);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
拦截Android的button控件的监听-hook
public class MainActivity extends AppCompatActivity {
TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.text);
mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("tww", "origin click");
}
});
hookOnClickListener(mTextView);
}
private void hookOnClickListener(View view) {
try {
// 得到 View 的 ListenerInfo 对象
Method getListenerInfo = View.class.getDeclaredMethod("getListenerInfo");
getListenerInfo.setAccessible(true);
Object listenerInfo = getListenerInfo.invoke(view);
// 得到 原始的 OnClickListener 对象
Class<?> listenerInfoClz = Class.forName("android.view.View$ListenerInfo");
Field mOnClickListener = listenerInfoClz.getDeclaredField("mOnClickListener");
mOnClickListener.setAccessible(true);
View.OnClickListener originOnClickListener = (View.OnClickListener) mOnClickListener.get(listenerInfo);
// 用自定义的 OnClickListener 替换原始的 OnClickListener
View.OnClickListener hookedOnClickListener = new HookedOnClickListener(originOnClickListener);
mOnClickListener.set(listenerInfo, hookedOnClickListener);
} catch (Exception e) {
Log.e("tww", "hook clickListener failed!", e);
}
}
public class HookedOnClickListener implements View.OnClickListener {
private View.OnClickListener origin;
HookedOnClickListener(View.OnClickListener origin) {
this.origin = origin;
}
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "hook click", Toast.LENGTH_SHORT).show();
Log.e("tww", "Before click, do what you want to to.");
if (origin != null) {
origin.onClick(v);
}
Log.e("tww", "After click, do what you want to to.");
}
}
}
https://www.jianshu.com/p/4f6d20076922
startActivity()--->