【Android端 APP 啟動時長獲取】啟動時長獲取方案及具體實施


一、什么是啟動時長?

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM