标签:
转载请说明.
一款应用的启动次数,无疑是一项重要的APM的检测指标.但Android的启动次数要考虑到一个重要的因素.那就是从后台切换回前台的时候.这算一次新的启动吗?
友盟和NewRelic作为国内外2家这项数据检测的领头羊,采用的方法是类似的.但是实现手段完全不一样.
友盟需要用户自己在代码中,用户手工写代码嵌入Activity生命周期的onPause()和onResume()方法中,执行newRelic的逻辑.
newRelic的用户完全无需用户关心这个.它会在编译时期自动在Activity的生命周期的onStop()和onStart()方法中嵌码.
认为App前后台切换的时间也不一样.友盟是30s,newRelic是5s.
通过ASM技术.在用户打包apk的时候动态嵌码.这项功能的实现以后再讲.
用户如果使用了newRelic的sdk后,会发现在系统的Activity的子类中onCreate()和onStop(),onStart()方法中都嵌码了. onCreate()方法的嵌码和Activity的交互Trace有关.暂不讨论.
开始的时候.
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("AppStateMon")); this.activitySnoozeTimeInMilliseconds = snoozeTimeInMilliseconds; executor.scheduleAtFixedRate(this, initialDelay, period, timeUnit); //sdk初始化的时候开始执行,以固定频率执行看门狗逻辑.检测app是否进入后台.(默认5s检测一次,打盹超过5s认为进入后台)
public void run() { synchronized (this.foregroundLock) { if ((this.foregrounded) && (getSnoozeTime() >= this.activitySnoozeTimeInMilliseconds)) { //如果app现在在前台但打盹时间大于规定时间.认为应用已经进入后台. notifyApplicationInBackground(); this.foregrounded = false; } } }
private long getSnoozeTime() //打盹时间 { synchronized (this.foregroundLock) { synchronized (this.snoozeLock) { if (this.snoozeStartTime == 0L) return 0L; return (System.currentTimeMillis() - this.snoozeStartTime); } } }
嵌入在用户的Activity的代码中.onStop()方法被嵌入了ApplicationStateMonitor.activityStopped(), onStart()方法嵌入了ApplicationStateMonitor.activityStarted().
所以Activity执行生命周期的2个方法时.会顺带执行以下2个方法.
public void activityStopped() { synchronized (this.foregroundLock) { synchronized (this.snoozeLock) { this.count -= 1L; if (this.count == 0L) //最关键的地方.如果应用进入后台,打盹时间才开始记录 this.snoozeStartTime = System.currentTimeMillis(); } } } public void activityStarted() { synchronized (this.foregroundLock) { synchronized (this.snoozeLock) { this.count += 1L; if (this.count == 1L) { this.snoozeStartTime = 0L; } } if (!(this.foregrounded)) { //如果app原来没在前台,则通知SDK已经进入前台.数据收集工作再次执行. log.verbose("Application appears to be in the foreground"); notifyApplicationInForeground(); this.foregrounded = true; } } }
上面逻辑走的通的一个重要原因是;一个ActivityA切换到另一个ActivityB,然后然后走的生命周期流程如下:
A.onStart()---->B.onCreate()-->B.onStart()--->A.onStop()-------(按home键进入后台)>B.onStop()----->B.onDestroty()
count=1 ------------------->count=2--------->count=1---------------------------->count=0--->打盹时间的初始值开始确定为当前时间
2个Activity的生命周期是重叠的.所以Activity切换的时候不会认为app在打盹. 一个Activity的展示生成是在生命周期的onResume()中.而用户的界面完全看不到才执行Activity的onStop()方法.
标签:
原文地址:http://www.cnblogs.com/laiqurufeng/p/4454174.html