文档章节

Android自动埋点的一种实现

fneg
 fneg
发布于 2016/03/02 22:39
字数 664
阅读 1959
收藏 4

在App开发过程中,埋点都要花费很多时间,而且还有遗漏没有埋的情况,能不能做到服务器下发哪些控件要埋,然后客户端自动埋。 前几天想出来了一个方案,今天实现了一个Demo,大概过程就是:遍历界面上所有View --> 如果View设置了OnClickListener,并且View的ID在配置文件中,那就替换OnClickListener为DelegentOnClickListener -->DelegentOnClickListener先调用埋点,然后再调用原先View的ClickListener。 

1.首先获取到控件的OnClickListener,Android 系统中没有相对应的API,查看View的源码,发现可以通过反射的方式获取到,Android系统将View相关Listener放到了一个内部类ListenerInfo中,从View 的mListenerInfo中可以获取到OnClickListener,大概的代码是这样的:

private View.OnClickListener getOnClickListener(View view) {
    boolean hasOnClick = view.hasOnClickListeners();
    if (hasOnClick) {
        try {
            Method method = View.class.getDeclaredMethod("getListenerInfo", null);
            if (null != method) {
                method.setAccessible(true);
                Object object = method.invoke(view, new Object[]{});
                if (null != object) {
                    Class listenerInfoClazz = object.getClass();
                    Field mOnClickListener = listenerInfoClazz.getDeclaredField("mOnClickListener");
                    if (null != mOnClickListener) {
                        mOnClickListener.setAccessible(true);
                        Object listener = mOnClickListener.get(object);
                        if (null != listener && listener instanceof View.OnClickListener) {
                            return (View.OnClickListener) listener;
                        }
                    }
                }
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
    return null;
}

2.遍历界面中的所有View,然后替换在配置文件中的View的OnClickListener,实现代码:

private void setClickListener(final View view) {
    if (null != view) {
        boolean hasOnClick = view.hasOnClickListeners();
        if (hasOnClick) {
            final View.OnClickListener listener = getOnClickListener(view);
            int id = view.getId();
            String name = getResources().getResourceName(id);
            //AdapterView不能设置OnClickListener
            if (!(view instanceof AdapterView)) {
                //检查是否在配置文件中,请求OnClickListener没替换过
                if (!(listener instanceof DelegentOnClickListener) &&
                        mTraceManager.isNeedTrace(this.getClass().getName(), name)) {
                    view.setOnClickListener(new DelegentOnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Log.e(TAG, "new clickListener");
                            if (null != listener) {
                                listener.onClick(v);
                            }
                            Log.e(TAG, v.getTag(v.getId()) + "");
                        }
                    });
                }
            }
        }
        if (view instanceof ViewGroup) {
            final ViewGroup viewGroup = (ViewGroup) view;
            int childCount = viewGroup.getChildCount();
            if (childCount > 0) {
                for (int i = 0; i < childCount; i++) {
                    View childView = viewGroup.getChildAt(i);
                    setClickListener(childView);
                }
            }
        }
    }

}

3.替换界面中所有的View的OnClickListener,实现代码: setClickListener(findViewById(android.R.id.content));

4.在Assets的配置文件中添加要追踪的Activity和View id。 这个Demo实现了大概的原理验证,距离真实的产品,还有很大的距离,包括替换所有View的OnClickListener的时机怎么选择,ListView,RecycleView的Item监听,还有OnTouchListenr,OnLongClickListener实现,通过设置DelegentTouchListener应该还可以实现界面的热力图,配置文件可以从服务器端下发,做到动态埋点,View可以有意识的setTag(id,object),然后埋点反序列化这个object,可以做到埋入一些参数信息,配置文件还可以扩展一下,有控件名称之类的。 配图很梦幻,如果实现了自动埋点,对运营和开发来说也是梦幻的。  

项目地址:https://github.com/fengcunhan/AutoTrace 


© 著作权归作者所有

共有 人打赏支持
fneg

fneg

粉丝 76
博文 43
码字总数 23812
作品 0
杭州
高级程序员
加载中

评论(2)

本人慧星撞地球
本人慧星撞地球

引用来自“PREPOET”的评论

https://github.com/mixpanel/mixpanel-android 有开源的埋点SDK,利用setAccessibilityDelegate

回复@PREPOET : 大哥这东西怎么用啊,能拿过来直接用吗?等待您的答复
PREPOET
PREPOET
https://github.com/mixpanel/mixpanel-android 有开源的埋点SDK,利用setAccessibilityDelegate
Android 可视化埋点方案

Tamic 原: www.jianshu.com/p/c65061358… 停止写技术博客一年后, 我又回归啦... 停止写技术博客一年后, 我又回归啦...,最近一年将会几个月间隔,输出更加高质量文章! 欢迎关注! #背景...

Tamic
08/31
0
0
Android 路由框架 - WMRouter

WMRouter是一款Android路由框架,基于组件化的设计思路,有功能灵活、使用简单的特点。 功能简介 WMRouter主要提供URI分发、ServiceLoader两大功能。 URI分发功能可用于多工程之间的页面跳转...

美团技术团队
09/24
0
0
Android 自定义进度条(指示器)

进度条分类 Android中进度条控件有3个(不算ProgressDialog),分别是ProgressBar、SeekBar和RatingBar,对于自定义样式来说又得按照需求分为2中情况,第一种是刻度型,第二种是循环类型。 ...

IamOkay
2014/12/14
0
4
使用Kotlin高效地开发Android App(二)

继上一篇文章介绍了项目中所使用的Kotlin特性,本文继续整理当前项目所用到的特性。 一.apply 函数 和 run 函数 with、apply、run函数都是Kotlin标准库中的函数。with在第一篇文章中已经介绍...

Tony沈哲
04/27
0
0
Android自动化页面测速在美团的实践

背景 随着移动互联网的快速发展,移动应用越来越注重用户体验。美团技术团队在开发过程中也非常注重提升移动应用的整体质量,其中很重要的一项内容就是页面的加载速度。如果发生冷启动时间过...

美团技术团队
07/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下单接口调优实战,性能提高10倍

概述 最近公司的下单接口有些慢,老板担心无法支撑双11,想让我优化一把,但是前提是不允许大改,因为下单接口太复杂了,如果改动太大,怕有风险。另外开发成本和测试成本也非常大。对于这种...

Sam哥哥聊技术
14分钟前
0
0
rabbitMQ的安装和配置

在Windows下进行rabbitMQ的安装 第一步:软件下载 在安装rabbitMQ之前,需要先安装Erlang。 Erlang官网:http://www.erlang.org/downloads rabbitMQ官网:http://www.rabbitmq.com/download....

狼王黄师傅
34分钟前
0
0
SAP产品的Field Extensibility

SAP开发人员的工作职责,除了实现软件的功能性需求外,还会花费相当的精力实现一些非功能性需求,来满足所谓的SAP Product Standard(产品标准)。这些产品标准,包含在SAP项目实施中大显身手...

JerryWang_SAP
39分钟前
0
0
Vue-Element-Upload

记录一下文件上传封装Js 代码示例 封装:uploadFile.vue <template> <el-upload v-model="attachment" ref="upload" class="upload-demo" :action="uploadUrl" ......

华山猛男
46分钟前
2
0
AWVS破解及使用手册

1.安装 因为是windows软件,比较简单,此部分略: 破解插件下载: 链接: https://pan.baidu.com/s/1x9LK9F3KvqDgTvXDjoSZnQ 提取码: 7k4u 2.创建扫描目标 2-1.Targets->Add Target 2-2.对话框...

硅谷课堂
49分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部