android埋点设计,老李分享:Android -自动化埋点 1

老李分享:Android -自动化埋点

当我们开发一款Android应用上线后,希望能收集一些用户操作的行为数据,比如用户在某个页面点击了多少次,在某个控件被点击了多少次,在某个页面停 留了多少时间等。这些数据收集起来可以交给数据分析师,他们可以统计出应用的PV或UV;或者统计应用中哪些页面最受欢迎,哪些控件点击率最低,从而来改 进应用。对于控件被点击多少次,一般做法是在控件点击事件中加入几行log代码,然后将此次的点击记录下来,最终发送到服务端,页面的点击也是类似,需要 在页面生命周期的开始加入log代码。这种插入log代码记录操作行为的方式定义为埋点。但麻烦的是,如果业务逻辑复杂,页面众多,控件众多,那就要在许多地方插入这些log代码。这是一件多么重复的事情呀!

那有没有可能自动化去埋点呢?就是将界面的打开、关闭以及控件点击的log记录放到统一的地方去处理,而不用在许多业务逻辑中加入log代码。这块统一的监控代码需要做到如下的事情:

1.可以监控到界面打开或者关闭,并将这种操作记录到log中2.当界面上的有控件被点击的时候,可以监控到哪个界面哪个控件被点击了,并将这些操作信息记录到log中3.要能实现埋点的定制,即对需要埋点的控件或者界面才记录它们的操作log

下面分析一下自动化埋点的思路。

自动化埋点的思路

首先对Android的Activity和UI做个基本的了解,然后再提供一些自动化埋点的思路。

1.Activity的生命周期

学习Android,Activity的生命周期是必修课。Activity的生命周期分为 onCreate,onStart,onResume,onPause,onStop和onDestroy,一个界面的展示和消失都会要经过这几个阶段, 所以如果监控了Activity的生命周期,就可以监控一个界面的打开、关闭以及用户在界面上停留的时间。实现这种监控方式,可以通过创造一个界面基类, 让所有业务界面去继承它,然后基类中重写所有Activity的生命周期方法,见如下代码。至于BaseActivity重写方法里做什么样的拦截处理, 这个会在下面说到。public BaseActivity extends Activity{

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

//这里对Activity的生命周期进行拦截,其他的方法也是

}}public BusinessActivity extends Activity{

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);   //一定要调用super的方法

//这里写一些业务代码

...

}}

2.Android的UI布局

Activity中的UI布局是层层嵌套的,很类似HTML的布局。在一个Activity中,“根”view是PhoneWindow$DecorView,可通过this.getWindow().getDecorView()获取到这个对象。通过实例说明一下,在一个空白的Activity界面中添加一个Button按钮,下图是利用hierarchyviewer截到的UI布局图。

图中的DecorView类似于HTML中的标签,里面嵌套的第一层Linearlayout类似于

标 签。Linearlayout中有两个子view,都是FrameLayout布局,它们类似于
标签。第一个 FrameLayout是应用的titlebar,TextView是titlebar上的文字;第二个FrameLayout中的内容就是 Activity中的布局。可以看到最外层的采用RelativeLayout布局,里面有个Button按钮。先做下简单了解,下面会说到它跟自动化埋点的关系。

3.Android事件传递机制

Activity中的UI布局是层层嵌套的,如果点击一个界面上的控件,点击事件的传递是由父视图向子视图传递,然后再传到具体的控件中,这个跟HTML中的点击事件冒泡一样。我们简单看一下Android的事件传递机制是怎么实现的。

在View中关于事件响应的方法有两个:public boolean dispatchTouchEvent(MotionEvent event)public boolean onTouchEvent(MotionEvent event)

而ViewGroup除了这个方法还有一个方法:public boolean onInterceptTouchEvent(MotionEvent event)

这些方法的返回值都是布尔型,返回的true或false决定了一个事件的响应能不能向下传递。我们来看一下这几个方法的作用。dispatchTouchEvent方法用于事件的分发,在Activity界面中所有的点击事件都要经过这个方法的分发。 返回true表示不分发事件,由当前的View来消费事件响应;返回false则继续往下分发,如果是ViewGroup则分发给 onInterceptTouchEvent进行判断是否拦截该事件。

onTouchEvent方法用于事件的处理,返回true表示消费处理当前事件,返回false则不处理,交给子控件进行继续分发。这个方法主要在普通控件中,比如Button。

onInterceptTouchEvent 是ViewGroup中才有的方法,View中没有,它的作用是负责事件的拦截,返回true的时候表示拦截当前事件,不继续往下分发,交给自身的 onTouchEvent进行处理。返回false则不拦截,继续往下传。这是ViewGroup特有的方法,因为ViewGroup中可能还有子 View,而在Android中View中是不能再包含子View的。

除了上述的事件,Android提供了一个OnTouchListener的监听器,当事件传递到控件的时候,如果控件注册了这个监听器,则会执行监听器中的onTouch方法。同时,如果它返回true,则事件也是不继续向下传递了。public boolean onTouch(View v, MotionEvent event)

上述的事件传递可以通过举一个例子说明,假设一个界面上有一个Button按钮,当我们touch down这个Button的时候,DOWN事件的传递如下:Activity->dispatchTouchEvent       Button->dispatchTouchEventButton->onTouchButton->onTouchEvent

这里的每一步返回false,事件就不会向下传递。当我们touch up这个Button的时候,UP事件的传递如下:Activity->dispatchTouchEvent       Button->dispatchTouchEventButton->onTouchButton->onTouchEvent    Button->click

可以看到,一个Button的click事件要经过上面几个过程。如果要监听一个Button的click事件,有一种思路是我们可以创建一个基类 BaseButton继承自Button,在回调OnClickListener的地方加入拦截代码。但是麻烦的是,点击控件不一定是Button,可能 是其他TextView或者Layout之类的,Android中控件很多,我们要造很多控件基类,这样应用中充满的控件都必须是我们自己创建的控件,这 样的设计是相当庞杂的。

那么我们考虑另外一种思路:让创建的BaseActivity基类重写Activity的dispatchTouchEvent方法,当touch button时,可以获取到按下(DOWN)和抬起(UP)时产生的MotionEvent对象。这个MotionEvent对象有两个方 法,getRawX()和getRawY(),通过这两个方法我们可以获取到“点击位置”在界面中的坐标。同时,上文中提到,Activity的UI是层 层嵌套的,通过“根”view可以层层遍历其下的子view以及所有子View上的控件,这些View和控件在屏幕中的坐标和宽高我们是可以获取到的。好 了,这样就可以搜索所有的子View或者控件的布局区域是否包含“点击位置”,从而来判断哪个View或控件被点击。具体判断可以通过如下代码实现。public boolean isInView(View view,MotionEvent event){

int clickX = event.getRawX();

int clickY = event.getRawY();

//如下的view表示Activity中的子View或者控件

int[] location = new int[2];

view.getLocationOnScreen(location);

int x = location[0];

int y = location[1];

int width = view.getWidth();

int height = view.getHeight();

if (clickX  (x + width) ||

clickY  (y + height)) {

return true;  //这个条件成立,则判断这个view被点击了

}

return false;}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值