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)文章
Kotlin標(biāo)準(zhǔn)庫函數(shù)使用分析及介紹
Kotlin提供了一個系統(tǒng)庫,是Java庫的增強(qiáng)。其中有很多函數(shù)在適配了Java的類型和方法同時使用Kotlin的語法。其中一些底層的函數(shù) 是使用比較廣泛的2022-09-09
Android Jetpack架構(gòu)中ViewModel接口暴露的不合理探究
這篇文章主要介紹了Android Jetpack架構(gòu)組件 ViewModel詳解,ViewModel類讓數(shù)據(jù)可在發(fā)生屏幕旋轉(zhuǎn)等配置更改后繼續(xù)存在,ViewModel類旨在以注重生命周期的方式存儲和管理界面相關(guān)的數(shù)據(jù)。感興趣可以來學(xué)習(xí)一下2022-07-07
Kotlin字符串操作在Android開發(fā)中的應(yīng)用示例代碼
本文介紹了Kotlin在Android開發(fā)中的字符串操作,包括多行字符串的創(chuàng)建、字符串插值、獲取字符串長度以及處理特殊字符等,通過示例代碼,展示了這些操作的實現(xiàn)方法,使開發(fā)者在處理字符串時更加高效便捷,感興趣的朋友一起看看吧2025-03-03
最近較流行的效果 Android自定義View實現(xiàn)傾斜列表/圖片
最近較流行的效果,這篇文章主要介紹了Android自定義View實現(xiàn)傾斜列表/圖片的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-06-06
Android編程實現(xiàn)檢測當(dāng)前電源狀態(tài)的方法
這篇文章主要介紹了Android編程實現(xiàn)檢測當(dāng)前電源狀態(tài)的方法,涉及Android針對當(dāng)前電源的電量、容量、伏數(shù)、溫度等的檢測技巧,非常簡單實用,需要的朋友可以參考下2015-11-11

