1.1 APP启动流程
(1)Launcher通过Binder进程间通信机制通知ActivityManagerService,它要启动一个Activity;
(2)ActivityManagerService通过Binder进程间通信机制通知Launcher进入Paused状态;
(3)Launcher通过Binder进程间通信机制通知ActivityManagerService,它已经准备就绪进入Paused状态, 于是ActivityManagerServicey利用Zygote.fork()创建一个新的进程,用来启动一个ActivityThread实例, 即将要启动的Activity就是在这个ActivityThread实例中运行;
(4)ActivityThread通过Binder进程间通信机制将一个ApplicationThread类型的Binder对象传递给ActivityManagerService,以便以后ActivityManagerService能够通过这个Binder对象和它进行通信;
(5)ActivityManagerService通过Binder进程间通信机制通知ActivityThread,现在一切准备就绪,它可以真正执行Activity的启动操作了。
1.2 APP启动分类
App 一般是从Launcher 启动的,常见App启动分为冷/热/暖三种启动情况:
(1)冷启动:启动应用前,后台没有该应用的进程,一般场景:程序安装后的第一次启动;应用程序被系统完全终止后再打开;
(2)热启动:此时程序仍然驻留在内存中,只是被系统从后台带到前台,因此程序可以避免重复对象初始化,加载布局和渲染。如果程序的某些内存被系统清除,则需要重新创建这些对象以响应启动事件。
(3)暖启动:它包含热启动和冷启动一系列的操作子集,比热启动消耗稍微多一点。它与热启动最大区别在于,它必须通过调用onCreate方法开始重新创建活动,也可以从传递给onCreate方法中保存的实例状态中获得某些对象的恢复。
热启动和暖启动很快,测试中关注的是冷启动时间。
安卓给出的建议时间:冷启动<=5s,热启动<=1.5s。
补充:冷启动流程
(1)加载并启动App;
(2)启动后立即为该App显示一个空白启动窗口;
(3)创建App进程(创建应用程序对象);
(4)创建MainActivity;
(5)加载布局,绘制渲染;
2. APP启动时间常用测试方法
2.1 AMS日志分析法
清除缓存数据:adb shell pm clear com.package.name
停止进程:adb shell am force-stop com.package.name
启动app:adb shell am start -W com.package.name/.activity.name
得到:
WaitTime:返回从 startActivity 到应用第一帧完全显示这段时间. 就是总的耗时,包括前一个应用 Activity pause 的时间和新应用启动的时间;
ThisTime:表示一连串启动 Activity 的最后一个 Activity 的启动耗时;
TotalTime:表示新应用启动的耗时,包括新进程的启动和 Activity 的启动,但不包括前一个应用Activity pause的耗时。
TotalTime是最重要的一个数据,开发者一般只要关心 TotalTime 即可,这个时间是应用真正启动的耗时。
2.2 代码埋点法
启动时间的代码埋点是在代码中埋下时间戳,上传服务器后通过开始和结束时间戳计算差值,从而得出启动时间。
目前比较流行的几个点位:
启动时间点:Application init开始,Application attachBaseContext开始,Application onCreate开始,Activity onCreate开始(启动时间点:目前业界比较认可的是attachBaseContext方法)
结束时间点:Activity onResume结束,Activity onWindowFocusChanged结束,View dispatchDraw结束;
推荐选择打点位置:
开始:Application attachBaseContext;
结束:核心View的dispatchDraw结束。
2.3录屏分帧法
(1)录屏命令adb shell screenrecord --bugreport --time-limit 30 /**/**/123.mp4
--bugreport
Add additional information, such as a timestamp overlay, that is helpful in videos captured to illustrate bugs.
(2)取出录制的视频adb pull /**/**/123.mp4 /**/**/
(3)使用可以按帧播放的视频软件打开(mac上quicktime就可以,win下可以用kmplayer),并按帧播放,视频左上角会显示每一帧的时间(精确到ms)和帧数。或者使用分帧软件ffmpeg分帧,例如一秒分成50帧,一帧就是0.02秒,计算点击APP后到启动用了多少帧,就可以得到启动时间。
命令:将视频拆帧,一秒拆成20帧:ffmpeg -i 123.mp4 -r 20 frames_%03d.jpg
3. 总结
以上是常用的app启动时间的测试方法,根据不同方法的优缺点,以及实际的测试场景和需求,可以选用合适的测试方法。
AMS日志分析法:
代码埋点法:
1、优点:易于覆盖多款设备、多个安卓版本的测试场景;以及方便追踪线上启动时间;
2、缺点:需要在代码中埋点打印时间戳;
录屏分帧法:
1、优点:可以测试真实的APP启动时间,业内常用的方法,可用于线下验证测试;
2、缺点:对于多款设备、多个安卓版本测试时,手工操作工作量大,以及无法追踪线上的启动时间;
3、补充:获取的时间是用户感受到的时间,和网络环境有关;可以用自动化检测特定元素出现判断启动成功,计算时间;
综上,在线下验证常用录屏拆帧的方法,获取的时间接近用户感受的时间。为避免手工操作覆盖多机型多版本时工作量大的问题,可以考虑引入自动化来实现;在线上测试获取启动时间,使用埋点打印时间,然后回传服务器得到数据。
补充:自动化平台成熟时,可以用图像识别算法,自动识别计算启动时间和结束时间。
工具:appium+mincap+opencv
appium用于自动化操作,minicap用于截图,opencv 用于图像识别
页面统计原理
1.app启动:命令执行的时候开始统计到图片数据匹配到的时候就是启动时间;
2.按钮点击:按钮点击后开始统计到图片数据匹配到的时候就是页面加载时间;