Example of hook click event under Android
- 2021-10-15 11:30:56
- OfStack
Hook is a kind of idea, that is, replacing the original events with our own events, so that we can do some cutting-in processing. The purpose is not to modify the original code, but also to avoid missing N multi-class processing.
Recently, it is necessary to set up statistical embedding points in the existing app. It seems that the coupling degree is too high if it is buried in the business code. Therefore, it is decided to use hook method to bury the event.
Here, first remember the basic process of hook for click events.
1. First, build a proxy class to implement View. OnClickListener, which is used to do the follow-up processing after clicking.
import android.view.View;
/**
* Realize click monitoring
*/
public class OnClickListenerProxy implements View.OnClickListener{
private View.OnClickListener mOriginalListener;
// Pass the original directly into the constructor OnClickListener
public OnClickListenerProxy(View.OnClickListener originalListener) {
mOriginalListener = originalListener;
}
@Override public void onClick(View v) {
if (mOriginalListener != null) {
mOriginalListener.onClick(v);
}
Log.d("LOGCAT","hooked!");
}
}
2. Carry out hook through the reflection mechanism of java
public static void hookOnClickListener(View view) {
try {
// Get View Adj. ListenerInfo Object
Method getListenerInfo = View.class.getDeclaredMethod("getListenerInfo");
// Modify getListenerInfo Is accessible (View In getListenerInfo No public)
getListenerInfo.setAccessible(true);
Object listenerInfo = getListenerInfo.invoke(view);
// Get Primitive OnClickListener Object
Class<?> listenerInfoClz = Class.forName("android.view.View$ListenerInfo");
Field mOnClickListener = listenerInfoClz.getDeclaredField("mOnClickListener");
mOnClickListener.setAccessible(true);
View.OnClickListener originOnClickListener = (View.OnClickListener) mOnClickListener.get(listenerInfo);
// Use custom OnClickListener Replace the original OnClickListener
View.OnClickListener hookedOnClickListener = new OnClickListenerProxy(originOnClickListener);
mOnClickListener.set(listenerInfo, hookedOnClickListener);
} catch (Exception e) {
Log.d("LOGCAT","hook clickListener failed!", e);
}
}
3. Call the above hookOnClickListener after the event you need hook
Button btnSend = (Button) findViewById(R.id.btn_send);
btnSend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
log.info("onClick");
}
});
HookManager.hookOnClickListener(btnSend);
4. As a statistical embedding point, it is inevitable to take point parameters
Set parameters in onClick of the original business code
private View.OnClickListener clickBtn = new Button.OnClickListener(){
@Override
public void onClick(View v) {
Map map = new HashMap();
map.put("name",v.getClass().getName());
v.setTag(v.getId(),map);
HookManager.hookOnClickListener(v);
}
};
Receive parameters in custom proxy onClick
@Override public void onClick(View v) {
if (mOriginalListener != null) {
mOriginalListener.onClick(v);
}
// Log.d("LOGCAT","hooked!"+v.getId());
// Get the parameters passed before
Object obj = v.getTag(v.getId());
Log.d("LOGCAT","hooked!"+v.getId()+"_"+obj.toString());
}
At this point, you can add follow-up operations at will in hook without changing the original logic code.
Related github address: https://github.com/codeqian/android-class-lib/tree/master/master/src/src/main/java/Hook