最近做项目 遇到一些埋点的需求,需要对相关点击事件,进行点击次数等用户行为的大数据统计。为了统一处理,对埋点使用了代理技术(也有使用其他技术的比如gradle自动配置注入属于无代码配置那种),工具类代码如下
package com.ytg.panasonic.tools;
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import java.lang.reflect.Field;
/**
* Created by ytg on 2018/1/11.
*/
public class HookUtils {
private static final String VIEW_CLASS = "android.view.View";
public static void hookListener(Activity mActivity, OnClickListener onClickListener) {
if (null != mActivity) {
View view = mActivity.getWindow().getDecorView();
getView(view, onClickListener);
}
}
public static void getView(View view, OnClickListener onClickListener) {
if (view instanceof ViewGroup) {
for (int i = 0, count = ((ViewGroup) view).getChildCount(); i < count; i++) {
getView(((ViewGroup) view).getChildAt(i), onClickListener);
}
}
viewHook(view, onClickListener);
}
public static void viewHook(View view, OnClickListener onClickListener) {
try {
Class viewClass = Class.forName(VIEW_CLASS);
Field feild = viewClass.getDeclaredField("mListenerInfo");
feild.setAccessible(true);
Object mListenerInfo = feild.get(view);//view对象中的mListenerInfo实例
if (null != mListenerInfo) {
Class listenerInfo2 = Class.forName("android.view.View$ListenerInfo");//反射创建listenerinfo
Field clickfeild = listenerInfo2.getDeclaredField("mOnClickListener");
clickfeild.setAccessible(true);
View.OnClickListener lis = (View.OnClickListener) clickfeild.get(mListenerInfo);
if (lis != null) {
View.OnClickListener lisproxy = new OnClickListenerProxy(lis, onClickListener);
clickfeild.set(mListenerInfo,lisproxy);//设置代理
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public interface OnClickListener {
void beforeInListener(View v);
void afterInListener(View v);
}
public static class OnClickListenerProxy implements View.OnClickListener {
private View.OnClickListener lis;
private HookUtils.OnClickListener mListener;
public OnClickListenerProxy(View.OnClickListener lis, OnClickListener mListener) {
this.lis = lis;
this.mListener = mListener;
}
@Override
public void onClick(View v) {
if (mListener != null) {
mListener.beforeInListener(v);
}
if (lis != null) {
lis.onClick(v);
}
if (mListener != null) {
mListener.afterInListener(v);
}
}
}
}
使用方法:
activity 或者fragment implements View.OnClickListener,HookUtils.OnClickListener
然后
textv.setOnClickListener(this);
HookUtils.hookListener(this,this);//这个得放在最后执行 可以封装在基类里边统一调用
,也可以根据自己的业务场景 进行改造。
@Override
public void beforeInListener(View v) {
Log.i("URI","beforeInListener");
}
@Override
public void afterInListener(View v) {
Log.i("URI","afterInListener");
}
@Override
public void onClick(View v) {
Log.i("URI","onClick");}
如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: https://leetcode.jp/项目埋点配置/