Android应用中埋点监控的思考与设计

更多内容请参照我的个人站点: http://stackvoid.com/

一款Android商业应用上线后,最关心的莫过于用户使用哪个模块比较频繁,哪个模块使用人群较少,产品可以根据这些数据来修正app以后的发展方向,使产生最大的商业价值。

通过埋点监控,我们可以深入业务的每一个细节,产生的用户行为可以通过所埋的点累计次数并将这些数据发送到数据中心,通过数据分析师就能给产品提出宝贵的意见,指导产品的演化方向。

本文基于我的上一篇博客Android 事件分发机制详解,如果你对事件分发机制不是特别了解的话,建议先去看一下这篇文章。

综述设计方案

我们的埋点方案要做到以下功能:

  1. Android界面上的空间被用户点击,需要记录下点击控件的名称并保存此信息。
  2. Android界面被打开或关闭,也需要记录此信息
  3. 最好能自动化完成,不需要修改大量代码,最好能定制

设计思路大体如下:

  1. 设计一个基类BaseActivity,它是继承自Activity,但是覆写了Activity的几个方法(后面会详细说明)。
  2. 利用广播来统一管理用户行为的Log信息。
  3. 数据积累到一定量,将用户行为数据发送到后台服务器。

BaseActivity基类的设计

利用Android事件分发机制,我们自定义的基类BaseActivity继承自Activity并重写Activity的dispatchTouchEvent方法(为什么要这么做?还请参考我的上一篇博客),以及重写Activity的所有生命周期方法。

重写Activity的生命周期以及事件分发方法

重写Activity生命周期的onStart()和onStop(){或者onDestory,这个根据自己的选择确定},来完成对界面开启和关闭的埋点记录。事件分发方法来检测ACTION_UP这个事件(也就是手指触动触摸屏抬起的那个事件),二者通过本地广播,将onStart或onStop这些事件广播出来并被接收处理。

 1 public class BaseActivity extends Activity {
 2  protected void onStart(){
 3      super.onStart();
 4      // 使用本地广播,高效更安全
 5      LoacalBroadcastManager bcManager = LocalBroadcastManager.getInstance(this);
 6      Intent intent = new Intent(ACTIVITY_START);//自定义的ACTIVITY_START
 7      bcManager.sendBroadcast(intent);
 8  }
 9  protected void onStop(){
10      super.onStop();
11      LoacalBroadcastManager bcManager = LocalBroadcastManager.getInstance(this);
12      Intent intent = new Intent(ACTIVITY_STOP);//自定义的ACTIVITY_STOP
13      bcManager.sendBroadcast(intent);
14  }
15  //.......可扩展
16  protected boolean dispatchTouchEvent(MotionEvent e){
17      if (e.getAction() == MotionEvent.ACTION_UP){
18          LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);
19             Intent intent = new Intent(VIEW_CLICK);
20             intent.putExtra(VIEW_CLICK, e);
21             broadcastManager.sendBroadcast(intent);
22      }
23  }

广播事件的处理

在处理广播的事件类中,我们获得VIEW_CLICK的Action就开始遍历当前Activity中所有的View,通过比对点击事件event的坐标个View的坐标,来判断是点击哪个View的event。

 1 public class BaseActivity extends Activity {
 2  //.......
 3  public class MonitorUserReceiver extends BroadcastReceiver {
 4      public void onReceive(Context context, Intent intent) {
 5          String action = intent.getAction();
 6          switch(action){
 7              case VIEW_CLICK:
 8                  MotionEvent event = intent.getParcelableExtra(VIEW_CLICK);
 9                  //递归遍历Activity中的所有View,找出被点击的View
10                  View clickView = searchClickView(view, event);
11                  //获取clickView的路径信息
12                  //生成log记录下来
13                  Log.writeLog();
14                  break;
15              case ACTIVITY_START:
16                  //可以知道某个界面被打开了,然后记录此次操作行为
17                  Log.writeLog();
18                  break;
19              case ACTIVITY_STOP:
20                  Log.writeLog();
21                  break;
22              //可扩展...
23          }
24      }
25      private View searchClickView(View view, MotionEvent event) {
26          View clickView = null;
27          if (isInView(view, event) &&
28              view.getVisibility() == View.VISIBLE) {  //当前View必须是可见的
29              if (view instanceof ViewGroup) {   //如果是类似Layout的ViewGroup,继续遍历它下面的子View
30                  ViewGroup group = (ViewGroup) view;
31                  for (int i = group.getChildCount() - 1; i >= 0; i--) {
32                      View childView = group.getChildAt(i);
33                      clickView = searchClickView(childView, event);
34                      if (clickView != null) {
35                          return clickView;
36                      }
37                  }
38              }
39              clickView = view;
40          }
41          return clickView;
42      }
43      public boolean isInView(View view,MotionEvent event){
44          int clickX = event.getRawX();    //获取点击事件的X和Y坐标
45          int clickY = event.getRawY();
46          //如下的view表示Activity中的子View或者控件
47          int[] location = new int[2];
48          view.getLocationOnScreen(location);
49          int x = location[0];
50          int y = location[1];
51          int width = view.getWidth();
52          int height = view.getHeight();
53          if (clickX < x || clickX > (x + width) ||
54              clickY < y || clickY > (y + height)) {
55              return true;  //此条件成立,说明这个view被点击了
56          }
57          return false;
58      }
59  }

记录View的路径

上面代码中提到要记录View的路径,我们可以通过给空间加Tag的方式,给此view空间位移的名字或ID,但一个Android app中的控件数量太多,想都加上Tag实在太麻烦,并且有漏加的风险。

Activity中的UI是层层嵌套的,其中根布局是PhoneWindow$DecorView,下面通过hierarchyviewer工具来举一个实例。

上图有一个TextView,如果按照我的采用的是View控件的路径方式标识方法应该是:

DecorView[0]>ActionBarOverlayLayout[0]>FrameLayout[0]>RelativeLayout[0]>TextView [0]":"helloworld"

在此路径前加上Activity的名字,便构成了控件View唯一的属性标识。例如我们在DemoActivity里有一个button,button名字为hello:

DemoActivity:DecorView[0]>ActionBarOverlayLayout[0]>FrameLayout[0]>RelativeLayout[0]>Button [0]":"hello"

DecorView,可通过this.getWindow().getDecorView()获得。其实在searchClickView方法中我们可以加上路径,找到我们需要的View,那么当前这个路径自然就知道了。 这种方法产生的问题有:产生的路径是:

DecorView>ActionBarOverlayLayout>FrameLayout>RelativeLayout>Button":"helloworld"

当有一个重名的Button时,根本分不清楚到底是哪一个Button。要是我们能产生类似DemoActivity:DecorView[0]>ActionBarOverlayLayout[0]>FrameLayout[0]>RelativeLayout[0]>Button [0]":"hello" 这种路径,就能完美解决这个问题了。所以需要去看 hierarchyviewer工具的源代码,看看它是怎么做到的。要是有读者分析过hierarchyviewer的源代码,欢迎交流该怎么获得这个路径。

将用户行为信息传到后台服务器

用户点击的log信息,我们可以用XML或JSON来格式化数据,然后存到app的目录下,一段时间后(这个自定义)开启新线程,将用户行为信息传送到后台服务器,这个步骤比较简单,就不上源码了。

不足之处

  1. 当前的APP使用这种DemoActivity:DecorView>ActionBarOverlayLayout>FrameLayout>RelativeLayout>Button":"helloworld"绝对路径,尽管app初期比较简单,但是若有工程师不注意使用相同的名字控件,会出现找到第一个就返回情况,后期还要继续研究hierarchyviewer的源代码,找到使用绝对路径的方法。
  2. 两个Button重叠,点击此Button,可能无法找到正确的一个,这个问题暂时没想出如何解决,只能靠工程师小心,不要加入重叠的Button。

更多内容请参照我的个人站点: http://stackvoid.com/

时间: 2024-08-04 16:28:58

Android应用中埋点监控的思考与设计的相关文章

android权限--android开发中的权限及含义(上)

android权限--android开发中的权限及含义(上) android.permission.EXPAND_STATUS_BAR 允许一个程序扩展收缩在状态栏,android开发网提示应该是一个类似Windows Mobile中的托盘程序 android.permission.FACTORY_TEST 作为一个工厂测试程序,运行在root用户 android.permission.FLASHLIGHT 访问闪光灯,android开发网提示HTC Dream不包含闪光灯 android.pe

关于Android应用中图片占用内存浅谈

从事过移动端应用开发的童鞋应该都清楚,内存是非常宝贵的资源.如果能很好的利用有限的内存,对应用性能的提升会有很大的帮助.在实际应用开发中图片内存占整个应用非常大的比重,我们只有了解图片是如何加载到内存中,才能更好的优化图片所占的内存. 那么对于图片在Android应用中的使用进行探讨一下. 图片所占内存大小=内存中图片高 * 内存中图片宽 * 每个像素所占字节数   1,那么图片的物理高宽和加载到内存中的高宽是否是一样的呢? 在应用中关于图片的加载一般分为两种情况,其加载到内存中的大小也是不一样

Android开发中的MVP架构(转)

写在前面,本博客来源于公众号文章:http://mp.weixin.qq.com/s?__biz=MzA3MDMyMjkzNg==&mid=402435540&idx=1&sn=1cd10bd9efaac7083575367a8b4af52f&scene=1&srcid=0910ARzPpBvVYPI1NDBZnixa#wechat_redirect 最近越来越多的人开始谈论架构.我周围的同事和工程师也是如此.尽管我还不是特别深入理解MVP和DDD,但是我们的新项目

Android Studio 中的FindBugs插件使用,轻松帮你发现Bug (转)

在日常开发过程中难免会因为一时疏忽而留下一些Bug,这些Bug就是埋在程序里的定时炸弹,如果不能及时铲除就会导致程序的不稳定,异常或闪退的现象,从而导致用户的体验的下降.那么怎么才能找出这些埋在程序里的定时炸弹呢?   对程序员来说最头疼的事情莫过于找Bug了,尤其是找自己程序中的Bug,因为人的思维是有误区的,他很容易陷入当时开发程序时的思维,这样就很难发现埋藏在程序中的Bug.接下来就给大家分享一个Bugs分析的工具FindBugs.   Findbugs是由 National Scienc

Android Studio中怎么使用DDMS工具?

随着android studio的广泛使用,开发人员对相关工具的使用需求更加凸显.昨天在一个android studio教程网站上,看到一篇有关DDMS工具使用的相关知识,感觉很不错,分享给大家,一起来看看吧,新技能get走起~~ 首先,我们需要了解的是DDMS工具是个什么鬼? 其实,DDMS(Dalvik Debug Monitor Service),是 Android 开发环境中的Dalvik虚拟机调试监控服务.可以进行的操作有:为测试设备截屏,查看特定行程中正在运行的线程以及堆信息.Log

Android系统上的键盘监控

键盘监控 键盘监控,顾名思义是在应用软件在运行时,用户在设备上的一举一动都将被详细记录下来,更多的实在使用者毫无觉察的情况下将屏幕内容以图片的形式.按键内容以文本文档的形式保存在指定的文件夹或发送到指定的邮箱.键盘监控,包括物理按键与软键盘的监控,通常监控的事件有:点击,长按,滑动等,这些时间在Android上表现出来的都是一系列的KeyEvent. 为了实现键盘的监控,从新开发一个输入法是不现实的,一般的操作就是在系统的输入法机制中添加接口回调.我们知道,再应用程序中拿到按键的回调一般是监听o

浅析android下如何通过jni监控wifi网络连接、dhcpcd执行和power电源控制

浅析android下如何通过jni监控wifi网络连接.dhcpcd执行和power电源控制 =============================================================================================================libs/android_runtime/android_net_wifi_Wifi.cpp部分jni接口static JNINativeMethod gWifiMethods[] = {

Android开发中的ANR问题如何避免?

在Android中, Activity Manager 和 Window Manager system services 会监控每个程序的运行,当程序出现如下三种种情况的时候就会弹出ANR的提示对话框: 1.用户在进行了一种操作后5秒钟没有响应. 2.broadCastReceiver所进行的操作在10秒内没有完成. 3.Service在20秒内没返回结果. 在APP运行中,出现了ANR是非常让人恼火的,会带来非常差的用户体验.所以在设计Android应用程序的时候要尽可能的避免产生ANR.那么

讨论Android开发中的MVC设计思想

最近闲着没事,总是想想做点什么.在时间空余之时给大家说说MVC设计思想在Android开发中的运用吧! MVC设计思想在Android开发中一直都是一套比较好的设计思想.很多APP的设计都是使用这套方案完成架构设计的. 谈到MVC我想分为以下几个点分点突进. 1.什么是MVC框架. 2.MVC如何工作 3.MVC的缺点 4.Android之MVC设计模式. 一.什么是MVC框架. MVC英文即Model-View-Controller,即把一个应用的输入.处理.输出流程按照Model.View.