在某些埋点场景中我们会需要采集时长属性,例如分析用户的 App 使用时长、用户观看时长等,那么有哪些可靠的计算时长方案?

考虑到用户可能是离线使用,所以可以采用的方案如下:

  1. 时间差
  2. 定时器

一、时间差

使用时间差计算时长需要记录下开始时间与结束时间,它们的差值也就是时长。一般来说有这两种思路来统计开始时间和结束时间:

  1. 设备的时间戳
  2. 设备的启动时长

Android 可以通过 System.currentTimeMillis() 方法来获取时间戳,iOS 可以通过 NSDate.date.timeIntervalSince1970 来获取时间戳。时间戳方案有一个很大的缺陷就是用户可以随意更改设备时间,而获取到的时间戳也会随着设备时间的调整而改变。

Android 可以通过 SystemClock.elapsedRealtime() 获取到启动时长,iOS 可以通过 NSProcessInfo.processInfo.systemUptime 获取到启动时长。启动时长不会收到用户更改设备时间的影响,但是如果重启设备那么启动时长也会随之重置。

神策 Android SDK 和 iOS SDK 正是采用了启动时长来计算时长,计算出的时长不会受到「修改设备时间」操作的影响。

二、定时器

相较于时间差的计算,定时器对性能的消耗会更大。

在 iOS 中,定时器使用不当会导致循环引用的问题;另外,当 NSTimer 被添加到主线程中,默认是会受到某些 UI 事件的影响,比如 UIScrollView 的拖动操作,需要修改 NSTimer 的 RunLoopMode。

综上,在神策分析 Android & iOS SDK 中,时长计算使用「设备启动时长」的差值来统计。