You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
android-notes/blogs/埋点.md

4.6 KiB

Android 全埋点

目录

  1. 思维导图

  2. 埋点概述

    • 事件采集

      • $AppStart / End 事件
      • $AppViewScreen 事件
      • $AppClick 事件
    • 整体思路

      • 自动拦截参考 Android 对 View 事件的处理逻辑
      • 自动插入参考编译器对 Java 代码的处理逻辑
    • 实现方式分类

      • 静态代理
        • AspectJ
        • ASM
        • javassist
        • AST
      • 动态代理
        • 代理 View.OnClickListener
        • 代理 Window.Callback
        • 代理 View.AccessibilityDelegate
    • 手动埋点

    • 自动化埋点

  3. $AppViewScreen 全埋点实现

  4. $AppStart / End 全埋点实现

  5. $AppClick 全埋点实现

  6. 参考

思维导图

埋点概述

事件采集

埋点就是预先手机用户的所有行为数据,采集的事件主要包括以下三种:

  1. $AppStart / End 事件

    指 App 启动以及 App 退出,启动包括冷启动和热启动,退出包括正常退出、退出后台以及 App 崩溃等。

  2. $AppViewScreen 事件

    指 App 页面浏览,对于 Android 来说就是指 切换 Activity。

  3. $AppClick 事件

    指 App 控件被电击。

采集的这三种事件中,最重要也最难采集的就是 $AppClick 点击事件,全埋点基本上也是围绕如何采集 $AppClick 事件。

整体思路

全埋点的整体思路,就是找到那个被点击的 View 的原处理逻辑,然后利用一定的技术原理,在原处理逻辑进行拦截,或在其中插入相应的埋点代码,从而达到自动埋点的效果。

至于如何做到自动拦截原点击事件的处理逻辑,一般参考 Android 系统 View 事件处理逻辑来进行的。

至于如何做到自动插入埋点代码,基本上都是参考编译器对 Java 代码的处理流程来进行的。即:

javaCode --> .java --> .class --> .dex
实现方式分类

按照在 “ 什么时候去代理或者插入代码 ” 这个条件来区分的话,Android 全埋点技术可以分为两种方式:

  1. 静态代理

    静态代理就是通过 Gradle Plugin 在编译期间 “ 插入 ” 或者修改代码( .class 文件 )。比如 AspectJ、ASM、javassist、AST 等方案均属于这种方式,这几种方式的处理时机可以参考下图:

  2. 动态代理

    动态代理即指在代码运行的时候去进行代理,比如常见的代理 View.OnClickListener、Window.Callback、View.AccessibilityDelegate 等方案均属于动态代理。

显然,静态代理明显优于动态代理。

$AppViewScreen 全埋点实现

页面浏览事件的监听还是很简单的,即 Application#ActivityLifecycleCallbacks,从 API 14 开始提供,它是 Application 的一个内部接口,提供了一系列回调方法,用于让开发者可以对 Activity 的所有生命周期事件进行集中处理(或者叫监控)。

需要注意的是,Android 是先回调接口函数,再去执行 Activity 本身的生命周期函数。

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();

        this.registerActivityLifecycleCallbacks(new MyActivityLifecycleCallback());
    }

    static class MyActivityLifecycleCallback implements ActivityLifecycleCallbacks{

        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            Log.i("2333","onActivityCreated");
        }

        @Override
        public void onActivityStarted(Activity activity) {
            Log.i("2333","onActivityStarted");
        }

        @Override
        public void onActivityResumed(Activity activity) {
            Log.i("2333","onActivityResumed");
        }

        @Override
        public void onActivityPaused(Activity activity) {
            Log.i("2333","onActivityPaused");
        }

        @Override
        public void onActivityStopped(Activity activity) {
            Log.i("2333","onActivityStopped");
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
            Log.i("2333","onActivitySaveInstanceState");
        }

        @Override
        public void onActivityDestroyed(Activity activity) {
            Log.i("2333","onActivityDestroyed");
        }
    }
}

$AppStart / End 全埋点实现

对于 App 的启动和退出事件,其实就是判断当前 App 是出于前台还是处于后台。而 Android 系统本身没有给 App 提供相关的接口来判断这些状态,所以只能借助其他方式来间接判断。

参考