一、什么是启动时长?

1、启动时长一般包括三种场景,分别是:新装包的首次启动时长,冷启动时长、热启动时长

冷启动 和 热启动 :

(1)冷启动:当启动应用时,后台没有该程序的进程,此时启动的话系统会分配一个新的进程给应用。

(2)热启动:程序的进程依然存在,启动时通过已有进程启动进入到Activity显示页面的,就是热启动,或者从Android官网来看我们获取到的其实是温启动时长,就是Activity不存在的情况。

(3)新装包的启动时长:

新装包的启动时长,预估是最长的,并且在5.0以下及5.0以上的Android系统上的表现不同,因为:Android 5.0和更高版本使用名为ART的运行时,它原生支持从APK文件加载多个DEX文件。在应用安装时,它会执行预编译,扫描classes(..N).dex文件然后将其编译成单个.oat文件用于执行。而Android5.0以下的系统不支持,只能在程序点击启动之后,进行多个dex文件的加载,如果是在Android5.0以下的机型上获取时长,就能明显看到新装包启动时长要比其他启动时长都要长。

其中冷启动的过程如下图所示:

系统开始启动Activity的时间,就是从start u0这个时间看的,准备启动这个Activity的时间,就是这条日志前面打印出来的这个时间:

12-14 16:45:51.483 I/ActivityManager( 1370): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10200000 cmp=com.ganji.android/.control.LaunchActivity bnds=[571,684][763,876] (has extras)} from uid 10021 on display 0

之后该Activity的第一帧展示出来的时候,会打印出Display的日志信息,如:

12-14 16:45:52.023 I/ActivityManager( 1370): Displayed com.ganji.android/.control.LaunchActivity: +521ms

从start u0到display第一帧的这个时间 包括了从启动进程到第一次布局与绘制的所有时间。这基本上是你需要知道的主要时间。它不包含用户点击app图标然后系统开始准备启动activity的时间,这是ok的

2、关于我们想要获取的三种场景的启动时长

(1)三种场景是启动的三种典型场景,这三种场景并没有包含将缓存和数据清除掉的情况;其中用户经历次数最多的是 “冷启动时长” 和“ 热启动时长”

(2)新装包的首次启动时长,一般情况下是最多的,在Android5.0以下系统上从APK文件加载多个dex文件的过程也包含在内。

冷启动时长居第二位,因为杀进程之后内存中的缓存会丢失,很多数据需要重新请求,并且需要重新启动进程;

热启动时长是最短的。

(3)我们想要获取启动时长的场景:

都是从初始的LaunchActivity页面进入到下一个的可操作的页面的时间;

比如以赶集网为例,新装包首次启动之后会跳转到选择城市的页面,我们需要获取的时长就是从 LaunchActivity的页面进入到SelectcityActivity的页面

因为用户一般会用到的场景是:选择城市进入到主页面,下次再启动都是直接进入到主页面,所以编写了uiautomator的脚本,能够通过UItest的方式选择城市;之后再分别获取 “冷启动时长” 和 “热启动时长”,即杀进程和正常退出程序的启动时长

二、如何获取?

1、因为通过logcat打印日志过滤ActivityManager的方式来获取启动时间,能够对其他APP也适用,因此最终确定用这种方式。

其中以赶集生活为例,新装包首次启动时长的获取,需要获取的是:从LaunchActivity的启动,到Displayed出来SelectCityActivity,刚开始用的是Displayed的后面的这个time的时长,但是跟开发确认之后,他说这个时间比用户的实际感知过程的时间还少一些,最终确定的是:

获取从start u0 LaunchActivity的时间到Display可操作的Activity的时间,拿到前面的时间节点之后,然后进行计算

以赶集网为例,三种场景下在 小米 4 + Android4.4.4的机型下,通过logcat抓到的日志如下:

新装包首次启动从Launch界面进入到选择城市的界面:

12-12 17:08:51.101 I/ActivityManager( 1191): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.ganji.android/.control.LaunchActivity} from pid 5656

12-12 17:08:58.141 I/ActivityManager( 1191): Displayed com.ganji.android/.control.LaunchActivity: +6s803ms

12-12 17:08:59.041 I/ActivityManager( 1191): START u0 {flg=0x200000 cmp=com.ganji.android/.control.BetterCityActivity (has extras)} from pid 5668

12-12 17:08:59.711 I/ActivityManager( 1191): Displayed com.ganji.android/.control.BetterCityActivity: +654ms

热启动时长:

12-12 17:11:23.571 I/ActivityManager( 1191): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.ganji.android/.control.LaunchActivity} from pid 6369

12-12 17:11:24.021 I/ActivityManager( 1191): Displayed com.ganji.android/.control.LaunchActivity: +264ms

12-12 17:11:25.311 I/ActivityManager( 1191): START u0 {cmp=com.ganji.android/.control.MainActivity} from pid 5668

12-12 17:11:27.311 I/ActivityManager( 1191): Displayed com.ganji.android/.control.MainActivity: +1s989ms

冷启动时长:

12-12 17:13:16.981 I/ActivityManager( 1191): START u0 {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.ganji.android/.control.LaunchActivity} from pid 6625

12-12 17:13:18.231 I/ActivityManager( 1191): Displayed com.ganji.android/.control.LaunchActivity: +1s237ms

12-12 17:13:19.231 I/ActivityManager( 1191): START u0 {cmp=com.ganji.android/.control.MainActivity} from pid 6637

12-12 17:13:22.811 I/ActivityManager( 1191): Displayed com.ganji.android/.control.MainActivity: +3s556ms

三种场景下,都需要从start u0 cmp = LaunchActivity的时间开始,到Displayed 下一个Activity的时间结束

2、当然,也可以通过录屏的方式,录屏的命令是:

adb shell screenrecord --bugreport /sdcard/launch.mp4

之后按Ctrl+C结束,然后将视频文件导出,之后使用可按帧播放的播放器即可。

使用播放器播放的时候,可以从用户点击屏幕发白发亮的那一刻算是开始时间,这个时间可以精确到ms,之后结束的话,就以你到达的页面,并且可以等待异步加载的都完成为止。

这个与 1 中的方法相比,获取的时间是会更长一些,因为包含了点击之后有了用户的touch操作,之后 系统响应,再到系统开始响应启动进程,创建Activity,加载视图,度量并进行Activity的整体显示的过程

并且通过logcat的方式,只能用在Activity从A跳转到B的这种情况,如果是Activity不变化,只是页面数据在刷新,logcat就无法通过ActivityManager打印出日志。

最终方案确定:

最终根据我们与开发的沟通,及通过这两种方式的对比,也为了后续能够方便通过程序写成自动化的形式,选择了第一种,并且增加了通过uiautomator完成城市选择和点击back键正常退出app的UI自动化的case来支持自动化实现。

三、最后确定的方案,方案的实施和工具实现

针对以上需求:

1、方便获取竞品的对比数据,需要在同一机型上执行,并且最好执行多次,选择一个平均值

2、方便方案的通用性,以及自动化实现

通过程序实现,主要包含以下过程:

1、自动装包

2、启动logcat,清除logcat的缓存,执行 adb  logcat -v time -s ActivityManager ,并将输出内容输出到某个文件

3、启动应用程序,通过adb shell am start LaunchActivity的方式,获取新装包的启动时间;之后通过uiautomator执行UI操作,完成热启动时间的获取,之后通过adb shell am force-stop pkg包名的方式杀进程,再启动完成冷启动时间的获取

3、将日志文件从手机中pull出来

4、对日志文件进行分析,因为前面都增加了-v time 的选项,log中能够打印出具体到ms的时间,可以根据你设置的规则,直接获取某条日志前面的时间

5、获取到开始时间和结束时间之后,用结束时间减去开始时间即可

备注:

参考资料————————————

APP的安装流程:

http://www.cnblogs.com/sunshine-anycall/p/3544345.html

Android APP的启动过程:

http://blog.csdn.net/freshui/article/details/8695463

http://www.androidchina.net/3851.html

http://mp.weixin.qq.com/s?__biz=MzA4MzEwOTkyMQ==&mid=2667376274&idx=1&sn=b35396dc9e2749da076b94979c9c5424&chksm=84f33fdcb384b6cac52b98a29cf379178afe69d6761e92b4b7ad35627c722ac3dbf6887a28c7&mpshare=1&scene=1&srcid=1011ObiSQI9cClmRpq89H8XD#rd

APK预编译提取Odex:http://blog.csdn.net/huangyabin001/article/details/46973625

Android MultiDex实践:https://gold.xitu.io/entry/5705b2712e958a0057a5f735

Android应用打破65K方法数限制:http://www.infoq.com/cn/news/2014/11/android-multidex

Android developer的官网针对Launch-Time Performance的内容如下:https://developer.android.com/topic/performance/launch-time.html

http://blog.csdn.net/huangyabin001/article/details/46973625

【Android端 APP 启动时长获取】启动时长获取方案及具体实施的更多相关文章

  1. 【Android端 APP GPU过度绘制】GPU过度绘制及优化

    一.Android端的卡顿 Android端APP在具体使用的过程中容易出现卡顿的情况,比如查看页面时出现一顿一顿的感受,切换tab之后响应很慢,或者具体滑动操作的时候也很慢. 二.卡顿的原因 卡顿的 ...

  2. 【Android端 APP 内存分析】使用工具进行APP的内存分析

    Android端可以通过adb 命令直接获取内存信息,当然Android studio也提供了对内存的监控分析工具,并且后续可以结合MAT做分析 今天介绍的是通过Android studio和MAT工 ...

  3. 【Android端APP 安装包检查】安装包检查具体内容及实现方法

    一.安装包检查的具体包含内容有哪些? 1.安装包检查的一般内容包括: 安装包基本信息检查: 文件大小: xx MB 包名: com.xx 名称:  xx 本次安装包证书与外网证书对比一致性:是 版本号 ...

  4. C#服务端通过Socket推送数据到Android端App中

    需求: 描述:实时在客户端上获取到哪些款需要补货. 要求: 后台需要使用c#,并且哪些需要补货的逻辑写在公司框架内,客户端采用PDA(即Android客户端 版本4.4) . 用户打开了补货通知页面时 ...

  5. Appium自动化时,如何快速获得Android app的包名和启动页

    在app自动化的时候,经常被问道如何知道app的包名和启动页名称.这个问题很简单: 1. 最直接的方式,去问开发啊,他们告诉你app的包名和启动页. 2. 如果你比较腼腆,又能看到/懂代码,自己把代码 ...

  6. Android Launcher分析和修改9——Launcher启动APP流程

    本来想分析AppsCustomizePagedView类,不过今天突然接到一个临时任务.客户反馈说机器界面的图标很难点击启动程序,经常点击了没有反应,Boss说要优先解决这问题.没办法,只能看看是怎么 ...

  7. Android手机app启动的时候第一个Activity必须是MainActivity吗

    原文:Android手机app启动的时候第一个Activity必须是MainActivity吗 Android手机APP启动的第一个Activity是可以自己设置的,不是必须的MainActivity ...

  8. Android在应用中依据包名启动另外一个APP

    以下为TestIntentData工程 MainActivity如下: package cn.testintentdata; import java.util.List; import android ...

  9. Android性能优化(一)之启动加速35%

    一.前言 随着项目版本的迭代,App的性能问题会逐渐暴露出来,而好的用户体验与性能表现紧密相关,从本篇文章开始,我将开启一个Android应用性能优化的专题,从理论到实战,从入门到深挖,手把手将性能优 ...

随机推荐

  1. MariaDB 10.1配置

    [mysqld]datadir=C:/Program Files/MariaDB 10.1/dataport=3306sql_mode="STRICT_TRANS_TABLES,NO_ENG ...

  2. openlayers3 画扇形

    参考了http://www.cnblogs.com/lingxue3769/archive/2011/11/01/2231409.html同学的博客 和 百度知道https://zhidao.baid ...

  3. HDP 2.3 Notes

    Hortonworks Data Platform 2.3.4.0-3485 [bug] /usr/hdp/2.3.4.0-3485/zookeeper/bin/zkEnv.sh 26 if [ -z ...

  4. IOS 中openGL使用教程1(openGL ES 入门篇 | 搭建openGL环境)

    OpenGL版本 iOS系统默认支持OpenGl ES1.0.ES2.0以及ES3.0 3个版本,三者之间并不是简单的版本升级,设计理念甚至完全不同,在开发OpenGL项目前,需要根据业务需求选择合适 ...

  5. c++学习一:指针基础

    1.指针优势,当数据量比较大时,通过指针直接访问数据量所在内存.处理更 加复杂的数据结构.例如:链表.二叉树.图等.2.指针本质是一种表示内存地址的数据类型,它和整型int和浮点数float一样 只是 ...

  6. 习课的视频播放器 video.js

    jsp <%@ page language="java" contentType="text/html; charset=utf-8" pageEncod ...

  7. JS获取IMG图片高宽

    前段时间在LJW写的touchslider.js轮播代码里添加自适应屏幕大小的功能时,遇到一个问题.不管用什么样的方法都无法获取到IMG标签的高宽,最后只有给图片定一个高宽的比例值:趁今天有空我就写了 ...

  8. MongoDB学习笔记(入门)

    一.文档的注意事项:1.  键值对是有序的,如:{ "name" : "stephen", "genda" : "male&quo ...

  9. 嵌入式: jffs2,yaffs2,logfs,ubifs文件系统性能分析

    在嵌入式领域,FLASH是一种常用的存储介质,由于其特殊的硬件结构,所以普通的文件系统如ext2,ext3等都不适合在其上使用,于是就出现了专门针对FLASH的文件系统,比较常用的有jffs2,yaf ...

  10. SQL Server复制情况下的高可用方案(一)镜像+复制

    数据库镜像可以与事务复制一起使用实现数据库整体的高可用性和高性能,其中镜像可以提供故障检测和故障转移,复制则用于实现读写分离. 数据库镜像涉及一个数据库的两个副本,这两个副本通常驻留在不同的计算机上. ...