Android下hook點擊事件的示例
Hook是一種思想,也就是將原來的事件,替換到我們自己的事件,方便我們做一些切入處理。目的是不修改原來的代碼,同時也避免遺漏的N多類里面處理。
最近需要在現(xiàn)有的app中設(shè)置統(tǒng)計埋點。去業(yè)務(wù)代碼里埋的話似乎耦合度太高。所以決定使用hook的方法對事件進(jìn)行埋點處理。
這里先記一下對點擊事件hook的基本流程。
1.先建一個代理類實現(xiàn)View.OnClickListener,用來做點擊后的后續(xù)處理。
import android.view.View; /** * 實現(xiàn)點擊監(jiān)聽 */ public class OnClickListenerProxy implements View.OnClickListener{ private View.OnClickListener mOriginalListener; //直接在構(gòu)造函數(shù)中傳進(jìn)來原來的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.通過java的反射機(jī)制進(jìn)行hook
public static void hookOnClickListener(View view) { try { // 得到 View 的 ListenerInfo 對象 Method getListenerInfo = View.class.getDeclaredMethod("getListenerInfo"); //修改getListenerInfo為可訪問(View中的getListenerInfo不是public) 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 OnClickListenerProxy(originOnClickListener); mOnClickListener.set(listenerInfo, hookedOnClickListener); } catch (Exception e) { Log.d("LOGCAT","hook clickListener failed!", e); } }
3.在你需要hook的事件后調(diào)用上面這個hookOnClickListener
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.作為統(tǒng)計埋點,不免需要帶點參數(shù)
在原業(yè)務(wù)代碼的onClick里設(shè)置參數(shù)
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); } };
在自定義的代理onClick里接收參數(shù)
@Override public void onClick(View v) { if (mOriginalListener != null) { mOriginalListener.onClick(v); } // Log.d("LOGCAT","hooked!"+v.getId()); //拿到之前傳遞的參數(shù) Object obj = v.getTag(v.getId()); Log.d("LOGCAT","hooked!"+v.getId()+"_"+obj.toString()); }
至此就可以在hook里隨意加入后續(xù)操作而不用改動原來的邏輯代碼了。
相關(guān)github地址: https://github.com/codeqian/android-class-lib/tree/master/utilDemo/app/src/main/java/Hook
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Flutter學(xué)習(xí)之構(gòu)建、布局及繪制三部曲
這篇文章主要給大家介紹了關(guān)于Flutter學(xué)習(xí)之構(gòu)建、布局及繪制三部曲的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Flutter具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04Android WebView交互傳遞json字符串并解析的方法
這篇文章主要給大家介紹了關(guān)于Android中WebView交互傳遞json字符串并解析的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對各位Android開發(fā)者具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-05-05Android Native庫的加載及動態(tài)鏈接的過程
這篇文章主要介紹了Android Native庫的加載及動態(tài)鏈接的加載過程,需要的朋友可以參考下2018-01-01Android橫豎屏切換及其對應(yīng)布局加載問題詳解
這篇文章主要為大家詳細(xì)介紹了Android橫豎屏切換及其對應(yīng)布局加載問題,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-04-04