android应用中自动化埋点的实现,Android应用中埋点监控的思考与设计

数据积累到一定量,将用户行为数据发送到后台服务器。

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工具来举一个实例。

129-94507.htmlvclVzZXIwMQ==" src="/uploadfile/Collfiles/20141011/2014101108335438.png" />

上图有一个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的目录下,一段时间后(这个自定义)开启新线程,将用户行为信息传送到后台服务器,这个步骤比较简单,就不上源码了。

不足之处

当前的APP使用这种DemoActivity:DecorView>ActionBarOverlayLayout>FrameLayout>RelativeLayout>Button:helloworld绝对路径,尽管app初期比较简单,但是若有工程师不注意使用相同的名字控件,会出现找到第一个就返回情况,后期还要继续研究hierarchyviewer的源代码,找到使用绝对路径的方法。

两个Button重叠,点击此Button,可能无法找到正确的一个,这个问题暂时没想出如何解决,只能靠工程师小心,不要加入重叠的Button。

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值