Android 全埋点解决方案(1)

简介: Android 全埋点解决方案

本文参考《Android全埋点解决方案》一书,并在实操中查漏补缺。

前言

为什么选择全埋点呢,因为传统的手动埋点虽然简单、扩展性强,但弊端也很明显:

  • 开发时间成本较高
  • 改动的时间成本也较高
  • 容易出现漏埋、埋错的情况
  • 代码侵入性强

但也不是说全埋点就一定没有弊端,比如扩展性较差。

经过调研,实际上都是以全埋点为主手动埋点为辅的情况,从而达到比较理想的埋点效果。

本文内容可能稍微有点长,但是很简单,别太长不看啊,最后有demo源码

页面

一般来说我们需要的数据就是,用户在哪个页面干了什么,也就是页面和事件,现在来说页面。

原理

通过生命周期可以计算出时长数据,以及页面对象。

Activity

页面有两个核心的需求数据:

  • 浏览时长
  • 页面唯一标示

这两个数据都挺好拿的,Application有一个registerActivityLifecycleCallbacks接口可以监测到activity的生命周期

有了生命周期,我们在onActivityResumed里面记录一下开始时间,然后在onActivityPaused中获取当前时间,就是整个页面的浏览时间

在生命周期方法中是有activity对象的,这样也可以拿到全路径作为唯一标示;

示例:

public static void registerActivityLifecycleCallbacks(Application application) {
        application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle bundle) {
            }
            @Override
            public void onActivityStarted(Activity activity) {
            }
            @Override
            public void onActivityResumed(Activity activity) {
                mBeginTime = System.currentTimeMillis();
            }
            @Override
            public void onActivityPaused(Activity activity) {
                trackAppViewScreen(activity);
            }
            @Override
            public void onActivityStopped(Activity activity) {
            }
            @Override
            public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {
            }
            @Override
            public void onActivityDestroyed(Activity activity) {
            }
        });
    }

onActivityPaused的时候我们调用了一下trackAppViewScreen方法,并传入当前activity,来看看trackAppViewScreen方法。

private static void trackAppViewScreen(Activity activity) {
        try {
            if (activity == null) {
                return;
            }
            if (mIgnoredActivities.contains(activity.getClass().getCanonicalName())) {
                return;
            }
            JSONObject properties = new JSONObject();
            //获取页面的参数
            if (activity.toString().contains("SecondActivity")) {
                String userId = activity.getIntent().getStringExtra("userId");
                properties.put("userId", userId);
            }
            properties.put("activity", activity.getClass().getCanonicalName());
            SensorsDataAPI.getInstance().track("$AppViewScreen", properties, mBeginTime);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

我们在trackAppViewScreen方法中创建了JSONObject对象properties,用来添加我们需要埋点的数据,比如页面的唯一标示key我们用activity表示,并取全路径作为value。


这里有一点需要注意的,我们除了可以收集一些固定参数之外,activity中intent的参数也是可以获取的,比如其他页面跳转到这个页面传的参数,我们同样可以获取到并作为埋点的参数使用的。


就像上面的SecondActivity,当MainActivity跳转到SecondActivity时传的userId是可以通过getIntent获取到的。


最后调用了SensorsDataAPI类的track方法,继续看

    public void track(@NonNull String eventName, @Nullable JSONObject properties, long beginTime) {
        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("event", eventName);
//            jsonObject.put("device_id", mDeviceId);
            JSONObject sendProperties = new JSONObject(mDeviceInfo);
            if (properties != null) {
                SensorsDataPrivate.mergeJSONObject(properties, sendProperties);
            }
            jsonObject.put("extras", sendProperties);
            jsonObject.put("beginTime", beginTime);
            jsonObject.put("endTime", System.currentTimeMillis());
            jsonObject.put("pageId", SensorsDataPrivate.getCurrentActivity().getClass().getCanonicalName());
            jsonObject.put("sessionId", UUID.randomUUID().toString().replace("-", ""));
            Log.i(TAG, SensorsDataPrivate.formatJson(jsonObject.toString()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

这里也很简单,先后创建了两个JSONObject,一个是最外层的jsonObject ,一个是作为参数使用的sendProperties,然后又把传过来的参数合并到sendProperties中,然后sendProperties作为extras的value使用。


endTime结束时间就取当前时间。


sessionId表示是这个埋点的唯一标示,看自己需求,非必须。


最后调用了Log打印出来,来看一下最后完整的数据:


{
  "event": "$AppViewScreen",
  "extras": {
    "app_name": "TrackDemo",
    "screen_width": 1440,
    "screen_height": 2621,
    "app_version": "1.0",
    "os_version": "10",
    "model": "Android SDK built for x86",
    "manufacturer": "Google",
    "activity": "com.yechaoa.trackdemo.ui.MainActivity"
  },
  "beginTime": 1603279291751,
  "endTime": 1603279293759,
  "pageId": "com.yechaoa.trackdemo.ui.MainActivity",
  "sessionId": "5dbb96807e634b6498f897784972ade3"
}


可以看到除了我们必要的参数之外,还有一些附加参数,比如手机型号、系统版本等等。

目录
相关文章
|
16天前
|
安全 Shell Android开发
Android系统 init.rc sys/class系统节点写不进解决方案和原理分析
Android系统 init.rc sys/class系统节点写不进解决方案和原理分析
29 0
|
1月前
|
XML Android开发 数据格式
android点击FrameLayout、LinearLayout等父布局没响应的原因以及解决方案
android点击FrameLayout、LinearLayout等父布局没响应的原因以及解决方案
31 2
|
XML Java Android开发
Android Studio开发APP启动程序时开屏简单动画效果快速有效解决方案
Android Studio开发APP启动程序时开屏简单动画效果快速有效解决方案
1357 0
Android Studio开发APP启动程序时开屏简单动画效果快速有效解决方案
|
3天前
|
Android开发
Android中Glide加载Https图片失败的解决方案
Android中Glide加载Https图片失败的解决方案
11 1
|
16天前
|
安全 编译器 API
Android HAL深入探索(5): 调试HAL报错与解决方案
Android HAL深入探索(5): 调试HAL报错与解决方案
22 1
|
16天前
|
存储 应用服务中间件 网络安全
Android 网络链接稳定性测试解决方案
Android 网络链接稳定性测试解决方案
20 0
|
25天前
|
编译器 调度 Android开发
构建高效Android应用:Kotlin协程的优雅解决方案
【4月更文挑战第14天】 在移动开发领域,性能优化和资源管理是提升用户体验的关键因素。随着Kotlin语言在Android平台上的普及,协程作为其核心特性之一,为开发者提供了一种轻量级的并发处理手段。本文将深入探讨Kotlin协程在Android应用中的运用,通过实例分析其如何简化异步任务,提升应用响应性,并保证代码的简洁与可维护性。我们将透过源码剖析、性能对比及最佳实践,揭示协程在现代Android开发中的重要角色。
|
2月前
|
JSON Android开发 数据格式
android 使用GSON 序列化对象出现字段被优化问题解决方案
android 使用GSON 序列化对象出现字段被优化问题解决方案
|
9月前
|
IDE Java 开发工具
Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8的解决方案
Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8的解决方案
|
8月前
|
Android开发
Android Studio 控制台中文乱码,解决方案都在这里了,完美解决
Android Studio 控制台中文乱码,解决方案都在这里了,完美解决