NO.1 Android 从$AppViewScreen说起

零蚀


全埋点的认识

  • 全埋点的理解

    全埋点是指工程师只需要使用少量代码,或者不使用代码就可以对用户的所有的行为数据进行搜集,并根据业务要求在行为数据中筛选出自己想要的数据。

    • $AppStart事件: 指应用的启动事件,同时包括冷启动和热启动,热启动是指应用程序从后台回复的情况。
    • $AppEnd事件: 指应用退出的情况,包括正常退出,按home键退出,应用被强杀,应用崩溃的等情况。
    • $AppViewScreen事件: 指应用程序的页面浏览,对于 Android应用程序来说就是切换activity和fragment。
    • AppClick事件: 应用的触控点击事件。通过自动找到点击事件的原处理逻辑,并在原处理逻辑的前后插入相应的埋点代码,进行事件的消息的“拦截”。

AppViewScreen全埋点方案

  • 原理概述

    $AppViewScreen 事件即是页面浏览事件,在Android事件中,是指activity或者fragment的切换事件。以activity为例,当一个activity执行到onResume方法时也就表示这个activity显示出来了。即在onResume埋点

    Application.ActivityLifecycleCallbacks是application的一个内部借口。从Android4.0开始使用,此接口提供了一系列的回调方法,让用户对activity的声明周期时间进行全面的管理。一个application可以注册多个callback方法,其内部定义了一个list用来用来保存所有的activityLifecycleCallBacks.

    如果我们的应用包含了三方库,且这个三方库的内部也包含activity的话,我们也是可以用Application.ActivityLifecyclerCallback.

  • 监听实现(简化版)

    创建Android lib(“sdk”)并且让module对其进行依赖。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9DvfHaGo-1583652711583)(media/15836425426761/15836494063649.jpg)]

    Application中实例化的监听对象

    public class SensorAPI {
        private static final Object key_lock=new Object();
        private static SensorAPI INSTANCE;
    
        /**
         * 设置单例模式
         * @param application
        */
        private SensorAPI(Application application){
        SensorPrivate.registerActivityLifeCallback(application);
        }
        public static SensorAPI init(Application application){
            synchronized (key_lock){
                if (null==INSTANCE){
                    INSTANCE=new SensorAPI(application);
                }
            }
    
    
            return INSTANCE;
        }
    
        // 获取对象
        public static SensorAPI getInstance(){
            return INSTANCE;
        }
    
        // 最终监控的AppViewScreen(所有的activity对象)并且打印出他们的信息
        public void track(String $AppViewScreen, JSONObject propertise) {
            Log.e("zero",propertise.toString());
        }
    
    }
    

    监听的实现方法

    public class SensorPrivate {
        // 记录所有的打开的activity类的列表
        private static List<Integer> list=new ArrayList<>();
        public static void trackAppViewScreen(Activity activity){
            try {
                // 判断hashcode,然后进行防止重复记录(看需求)
                if (null!=activity&&!list.contains(activity.getClass().hashCode())){
                 JSONObject propertise=new JSONObject();
                 propertise.put("$activity",activity.getClass().getCanonicalName());
                 SensorAPI.getInstance().track("$AppViewScreen",propertise);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
    
        }
    
    
        // 注册监听回调
        public static void registerActivityLifeCallback(Application application){
            application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
                @Override
                public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    
                }
    
                @Override
                public void onActivityStarted(Activity activity) {
    
                }
    
                @Override
                public void onActivityResumed(Activity activity) {
                    trackAppViewScreen(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) {
    
                }
            });
        }
    }
    
    

    module中的运用

    //MyApplication
    SensorAPI.init(this);
    // MainActivity 添加跳转按钮
    public void IntentClick(View view) {
        startActivity(new Intent(this,SecondActivity.class));
    }
    

    print logcat

    E/zero: {"$activity":"com.example.trackapplication.MainActivity"}
    E/zero: {"$activity":"com.example.trackapplication.SecondActivity"}
    
  • 监听和权限冲突

    在我们申请权限的时候,我们在允许/禁止的时候系统会自行调用onRequestPermissionResult方法,然后再次调用当前Activity的onResume方法,会导致我们埋点的SDK重新走一次track方法,导致埋点的数据不准确。

    为此,我们可以用一个容器例如list来记录这个埋点的过程从而使得,在申请权限的时候我们可以通过扫描忽略的activity来甄别是否要打印出相关信息


$AppStart(AppEnd)全埋点方案

  • 简介

    这两个事件主要是判断应用所处的状态,是前台还是后台。而Android自身并没有给出相对应的接口。

  • 解决方案

    原书在判断应用是否是APpEnd的情况下,运用的是记录当前的activity的onStart和上一个activity的onPause是否中间相隔>30s未启动,从而判断是否是当前的app出现了退出/卸载等情况。(但是记载时间戳的这种方法只存于不依赖任何外界情况的条件下,所以这种方案的局限性很大,并且用户卸载,或者崩溃,瘫痪等情况导致用户不在打开应用,也会导致$AppEnd事件丢失)

    文章内容为《Android 全埋点解决方案》学习笔记


🔗 前言
🔗 Android 专题列表
🔗 Android 全埋点 专题列表
🔗 NO.2 Android OnClick全埋点-1
🔗 NO.3 Android OnClick全埋点-2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零蚀zero eclipse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值