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.
 

5.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) {
        }

        @Override
        public void onActivityStarted(Activity activity) {
        }

        @Override
        public void onActivityResumed(Activity activity) {
        }

        @Override
        public void onActivityPaused(Activity activity) {
        }

        @Override
        public void onActivityStopped(Activity activity) {
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        }

        @Override
        public void onActivityDestroyed(Activity activity) {
        }
    }
}

$AppStart / End 全埋点实现

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

方案 含义 是否需要权限 特点
方案一 RunningTask 5.0 此方法已废弃
方案二 RunningProcess
方案三 ActivityLifecycleCallbacks 简单、代码量少
方案四 UsageStatsManager 需要用户手动授权
方案五 无障碍服务 需要用户手动授权
方案六 读取 /proc 目录下的信息 效率

详见:埋点之应用前后台判断

$AppClick 全埋点实现

AspectJ 实现方式

代理 View.OnClickListener

参考

《神策数据 Android 全埋点技术白皮书》

https://github.com/wenmingvs/AndroidProcess