我來了我來了,今天給大家介紹一下數(shù)據(jù)埋點(diǎn)相關(guān)知識
首先數(shù)據(jù)埋點(diǎn)分為三種。
一 代碼埋點(diǎn)
這種是我接觸最多的埋點(diǎn)方式,直接進(jìn)行代碼侵入埋點(diǎn)舉個例子
viewById.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
execute();
// Log.i(TAG, "after: " + System.currentTimeMillis() -beforTime);
}
});
logi這一行就屬于代碼埋點(diǎn)
優(yōu)點(diǎn):靈活性高可以定制想要的屬性和字段
缺點(diǎn):對代碼侵入,埋點(diǎn)必須熟悉業(yè)務(wù)的專業(yè)人員,工作量比較大,更新埋點(diǎn)通過發(fā)版來進(jìn)行
二 全埋點(diǎn)
兩種實(shí)現(xiàn) 第一種hook系統(tǒng)方法,比如hook所有view的onclick事件 ,然后替換成自己的onclick事件。
舉個例子
public static void hookListener(Activity mActivity) {
if (null != mActivity) {
View view = mActivity.getWindow().getDecorView();
getView(view);
}
}
private static void getView(View view) {
if (view instanceof ViewGroup) {
for (int i = 0, count = ((ViewGroup) view).getChildCount(); i < count; i++) {
getView(((ViewGroup) view).getChildAt(i));
}
}
viewHook(view);
}
private static void viewHook(View view) {
try {
Class viewClass = Class.forName("android.view.View");
Field feild = viewClass.getDeclaredField("mListenerInfo");
feild.setAccessible(true);
Object mListenerInfo = feild.get(view);//view對象中的mListenerInfo實(shí)例
if (null != mListenerInfo) {
Class listenerInfo2 = Class.forName("android.view.View$ListenerInfo");//反射創(chuàng)建listenerinfo
Field mOnClickListener = listenerInfo2.getDeclaredField("mOnClickListener");
mOnClickListener.setAccessible(true);
View.OnClickListener lis = (View.OnClickListener) mOnClickListener.get(mListenerInfo);
if (lis != null) {
View.OnClickListener mOnClickListenerWrapper = new OnClickListenerWrapper(lis);
mOnClickListener.set(mListenerInfo,mOnClickListenerWrapper);//設(shè)置代理
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
這樣hook掉所有View的點(diǎn)擊事件,就可以監(jiān)聽到所有view的點(diǎn)擊事件了,缺點(diǎn)由于使用反射會消耗app的性能,影響運(yùn)行速度。
第二種 aop方法,簡單解釋一下aop,java是面向?qū)ο缶幊蹋琣op面向切面編程,通俗的講它不關(guān)心對象,他關(guān)注的是某一個點(diǎn),比如咱們方法中的單擊事件,這就是一個點(diǎn),意思就是所有的單擊事件都是我的點(diǎn),我是根據(jù)點(diǎn)來進(jìn)行編程,只要是這個點(diǎn)就歸我管。
看一個例子
@Aspect
public class AspectJAnn {
private static final String TAG = "AspectJAnn";
@Before("execution(* android.view.View.OnClickListener.onClick(..))")
public void clickMethod(JoinPoint joinPoint) {
try {
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
View pointView = (View) args[i];
String entryName = BaseApplication.getInstance().getResources().getResourceEntryName(pointView.getId());
if (pointView instanceof TextView){
entryName = ((TextView) pointView).getText().toString();
}
AnnHelper.get().onAnnClick(entryName, "no_from", ActivityCollector.getCurrentActivity().getClass().getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
寫了這個類,不用任何地方調(diào)用,我編譯之后,所有的onclick方法都會執(zhí)行到這里。(jar中包的除外,只能是我們自己寫的代碼,就是省去了我們自己寫)
原理:通過一個插件,在編譯時期(編譯時期是重點(diǎn))把這個方法的調(diào)用自動插入到所有onclick方法中了,這也就是jar包中的單擊方法不能插入的原因。可以通過app反編譯后看到具體的實(shí)現(xiàn),我雖然看過但是忘記截圖了,這里就不上圖了
這種方案校對上一種方案的優(yōu)點(diǎn),編譯時候加的代碼,不會影響運(yùn)行性能,但是會影響編譯速度,不支持jar包,不支持喇嘛大表達(dá)式,而且導(dǎo)入包的時候我經(jīng)歷了各種莫名其妙絕望的錯誤,最后還好在各種朋友的幫助下完成了集成(朋友是我們一生的財(cái)富)。
附上一篇使用說明和github地址:使用說明,github地址
優(yōu)點(diǎn):沒有代碼侵入,工作量很小
缺點(diǎn):靈活性太差,拿不到特別想要的數(shù)據(jù)。
三 可視化埋點(diǎn)
簡單介紹,這種沒有太多用武之地,說完你就明白了。
類似全埋點(diǎn)的基礎(chǔ)上,根據(jù)后臺返回的具體坐標(biāo) 比如距上下左右都是50dp的位置。這樣弊端 如果視圖修改就沒什么用了。也沒有遇到過這種埋點(diǎn)
參考 神策數(shù)據(jù) Android 埋點(diǎn)白皮書。