Android 应用启动时间统计方式

这篇具有很好参考价值的文章主要介绍了Android 应用启动时间统计方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

启动时间

Time To Initial Display (TTID)

TTID 指标用于测量应用生成第一帧所用的时间,包括进程初始化(如果是冷启动)、activity 创建(如果是冷启动/温启动)以及显示第一帧。

在 Android 4.4(API 级别 19)及更高版本中,Logcat 提供了一个 Displayed 值,用于测量从启动进程到完成在屏幕上绘制 activity 的第一帧之间经过的时间。

在 Android 4.4(API 级别 19)及更高版本中,Logcat 包含一个输出行,该行包含名为 Displayed 的值。此值代表从启动进程到在屏幕上完成对应 activity 的绘制所用的时间。经过的时间包括以下事件序列:

  • 启动进程。
  • 初始化对象。
  • 创建并初始化 activity。
  • 扩充布局。
  • 首次绘制应用。

日志如下:

Android 应用启动时间统计方式

I/ActivityTaskManager: Displayed {包名}/.Activity: +414ms

Time To Full Display (TTFD)

TTFD 指标用于测量应用生成具有完整内容的第一帧所用的时间,包括在第一帧之后异步加载的内容。一般情况下,这是从网络加载的列表相关内容(由应用上报)。

在延迟加载的场景下,应用的 TTID 不包括所有资源的加载时间,可以将 TTFD 视为单独的指标:
例如,应用的界面可能已完全加载,并绘制了一些文本,但尚未显示应用必须从网络中加载的图片。
要测量 TTFD,所有内容显示后在 Activity 中手动调用 reportFullyDrawn() 方法。之后,可以在 Logcat 中看到:

举个例子:

   override fun onResume() {
        super.onResume()
        reportFullyDrawn()
    }
2023-03-19 13:20:38.450 1449-1472/? I/ActivityTaskManager: Fully drawn {包名}/.MainActivity: +856ms

本地测量启动时间方式

ADB

adb 启动一个应用程序:

adb shell am start -W {包名}/.MainActivity

Android 应用启动时间统计方式

Jetpack Macrobenchmark

也可以使用 Jetpack Macrobenchmark: Startup 测量应用程序启动时间。

使用 Jetpack Macrobenchmark 对用例进行基准测试

借助 Macrobenchmark,可以直接针对在搭载 Android M (API 23)更高版本系统的设备上运行的应用编写启动和运行时性能测试

建议将 Macrobenchmark 与最新版本的 Android Studio(2021.1.1 或更高版本)搭配使用,因为该版本的 IDE 中提供了可与 Macrobenchmark 集成的新功能。使用早期版本 Android Studio 的用户可以根据本主题后面部分的额外说明来处理跟踪文件。

基准测试通过 Macrobenchmark 库中的 MacrobenchmarkRule JUnit4 规则 API 提供:

    @get:Rule
    val benchmarkRule = MacrobenchmarkRule()

    @Test
    fun startup() = benchmarkRule.measureRepeated(
        packageName = "mypackage.myapp",
        metrics = listOf(StartupTimingMetric()),
        iterations = 5,
        startupMode = StartupMode.COLD
    ) { // this = MacrobenchmarkScope
        pressHome()
        val intent = Intent()
        intent.setPackage("mypackage.myapp")
        intent.setAction("mypackage.myapp.myaction")
        startActivityAndWait(intent)
    }
  

自测:

gradle配置:

defaultConfig {
        applicationId "com.example.myapplication"
        minSdk 23
        targetSdk 33
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
implementation 'androidx.test.ext:junit-ktx:1.1.5'
implementation 'androidx.benchmark:benchmark-macro-junit4:1.1.0-beta05'
implementation 'androidx.test.uiautomator:uiautomator:2.2.0'

Android 应用启动时间统计方式

生产环境测量启动时间

Android Vitals

在 Android Vitals(在 Google Play 控制台上)的 App 启动时间页面上,可以看到有关你的应用程序何时从 cold、warm 和 hot 系统状态启动的详细信息。

Android 应用启动时间统计方式

Android 应用启动时间统计方式

Android 应用启动时间统计方式

当您的应用启动时间过长时,Android Vitals 可以通过 Play 管理中心提醒您,从而帮助提升应用性能。Android Vitals 在您的应用出现以下情况时将其启动时间视为过长:

  • 冷启动用了 5 秒或更长时间。
  • 温启动用了 2 秒或更长时间。
  • 热启动用了 1.5 秒或更长时间。

Android 应用启动时间统计方式

  • 受影响的时段/日数量(个):用户遇到至少 1 次冷启动时间超过 5 秒的情况的活跃日数量。启动时间是指从用户启动您的应用到起初的几帧画面显示在屏幕上所需的时间。如果用户在一天内使用过您的应用,当天即计为一个活跃日。
  • 受影响的时段/日百分比:用户在各个系统状态下遇到启动时间过长问题的工作时段所占的百分比。冷启动时间过长:5 秒或更长。(用户遇到至少 1 次冷启动时间超过 5 秒的情况的活跃日百分比。启动时间是指从用户启动您的应用到起初的几帧画面显示在屏幕上所需的时间。如果用户在一天内使用过您的应用,当天即计为一个活跃日。)
  • 工作时段数:系统已记录的工作时段的大概数量。
  • 第 90/99 个百分位:10%/1% 的活跃日中,用户在您的应用中遇到启动时间过长的问题。
  • 第90个百分位(毫秒):在 10% 的活跃日中,用户遇到了启动时间超过以下值的情况。
  • 第99百分位(毫秒):在 1% 的活跃日中,用户遇到了启动时间超过以下值的情况。

注意:

第一个是如果应用程序在同一天从同一系统状态启动多次,则会记录当天的最长启动时间。所以只记录每天最差的启动时间,而不是任何发生的时间。

第二个(也是更重要的)是当应用程序的第一帧完全加载时。(TTID 指标)Android Vitals 使用初步显示所用时间指标。初步显示所用时间 (TTID) 指标用于测量应用生成第一帧所用的时间,包括进程初始化(如果是冷启动)、activity 创建(如果是冷启动/温启动)以及显示第一帧。当应用程序的第一帧完全加载时,将跟踪启动时间,即使它不是用户可以交互的页面。示例:如果应用程序以启动画面启动,则启动时间等于显示启动画面所需的时间。对于带有加载或启动画面的应用程序来说,因为 Android Vitals 只测量加载屏幕显示之前的时间,而不是用户可以与应用交互的时间,所以得到的数据比实际启动时间更短。



 

Firebase 性能监控

Firebase Performance Monitoring (google.com)

对于原生应用会自动衡量应用启动时间。

Performance Monitoring 使用跟踪记录来收集有关应用中受监控进程的数据。跟踪记录是一种报告,包含两个时间点之间在应用中捕获的数据。

Performance Monitoring 会自动收集与应用生命周期相关的多个跟踪记录。所有这些跟踪记录都类似于计时器,因为它们会衡量进程运行所需的时间(“时长”)。

应用启动跟踪记录 - 此跟踪记录衡量用户打开应用到应用响应之间的时间。在控制台中,此跟踪记录的名称为 _app_start。此跟踪记录收集的指标为“时长”。

  • 在应用的 FirebasePerfProvider ContentProvider 完成其 onCreate 方法时启动。
  • 在调用第一个活动的 onResume() 方法时停止。

请注意,如果应用程序不是由Activity冷启动(例如,由服务或广播接收器),则不会生成任何跟踪。

这是 Firebase 性能监控仪表板中应用启动时间指标的示例:

Android 应用启动时间统计方式

自定义跟踪

如果你的应用程序在启动时有启动动画,可以使用 Firebase Performance Monitoring 自定义代码跟踪手动跟踪启动时间。为特定应用代码添加自定义监控  |  Firebase Performance Monitoring (google.com)

实现方式:

1.创建 DVStartupTimeProvider

ContentProvider 初始化在 Application.onCreate 之前执行,可以使用其初始化 Firebase。通过调用 StartupTrace.onColdStartInitiated 方法注册 activity 生命周期回调,在用户可以交互的第一个页面 的 onResume 方法中停止跟踪。

package com.xxx.startup

import android.content.ContentProvider
import android.content.ContentValues
import android.database.Cursor
import android.net.Uri
import android.os.Handler
import android.os.Looper
import com.google.firebase.FirebaseApp

/**
 * @createTime 2023/3/26 16:08
 * @description
 */
class DVStartupTimeProvider : ContentProvider() {
    private val mainHandler = Handler(Looper.getMainLooper())
    override fun onCreate(): Boolean {
        FirebaseApp.initializeApp(context!!)
        DVStartupTrace.onColdStartInit(context!!)
        mainHandler.post(DVStartupTrace.StartFromBackgroundRunnable)
        return true
    }

    override fun query(
        uri: Uri,
        projection: Array<out String>?,
        selection: String?,
        selectionArgs: Array<out String>?,
        sortOrder: String?
    ): Cursor? {
        return null
    }

    override fun getType(uri: Uri): String? {
        return null
    }

    override fun insert(uri: Uri, values: ContentValues?): Uri? {
        return null
    }

    override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
        return -1
    }

    override fun update(
        uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?
    ): Int {
        return -1
    }
}

2. AndroidManifest 中配置DVStartupTimeProvider

需要在 AndroidManifest.xml 上声明 ContentProvider,以便在应用程序启动时调用。该 initOrder 属性定义了可能的最大整数,因此该 ContentProvider 是第一个被调用的。
因为在 DVStartupTimeProvider 上初始化 Firebase ,因此禁用了 FirebaseInitProvider 。

<provider  
	android:name="com.google.firebase.provider.FirebaseInitProvider"  
	android:authorities="${applicationId}.firebaseinitprovider"  
	tools:node="remove" />

<provider  
	android:authorities = "${applicationId}.startup-time-provider"  
	android:exported = "false"  
	android:initOrder = "2147483647"  
	android:name = "com.xxxx.startup.DVStartupTimeProvider" />  

 
3.创建 StartupTrace

该 StartupTrace 类将启动自定义跟踪,然后侦听所有 activity.onResume方法。在第一个非加载动画页面的 onResume 方法中停止跟踪。

package xxxx

import android.app.Activity
import android.app.Application
import android.content.Context
import android.os.Bundle
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ProcessLifecycleOwner
import com.google.firebase.perf.FirebasePerformance
import com.google.firebase.perf.metrics.Trace
import com.transsion.carlcare.HomeActivity
import java.util.concurrent.TimeUnit

/**
 * @createTime 2023/3/26 16:16
 * @description
 */
object DVStartupTrace : Application.ActivityLifecycleCallbacks, LifecycleObserver {
    private val START_SLOWEST_TIME = TimeUnit.MINUTES.toMillis(1)
    var appStartTime: Long = 0
    private var onCreateTime: Long = 0
    var isStartedFromBackground = false
    var atLeastOnTimeOnBackground = false
    private var isRegisteredForLifecycleCallbacks = false
    private lateinit var appContext: Context

    private var trace: Trace? = null

    var isTooSlowToInitUI = false

    fun onColdStartInit(context: Context) {
        appStartTime = System.currentTimeMillis()
        trace = FirebasePerformance.getInstance().newTrace("cold_startup_time")
        trace?.start()

        val applicationContext = context.applicationContext
        if (applicationContext is Application) {
            applicationContext.registerActivityLifecycleCallbacks(this)
            ProcessLifecycleOwner.get().lifecycle.addObserver(this)
            isRegisteredForLifecycleCallbacks = true
            appContext = applicationContext
        }
    }

    private fun unregisterActivityLifecycleCallbacks() {
        if (!isRegisteredForLifecycleCallbacks) {
            return
        }
        (appContext as? Application)?.unregisterActivityLifecycleCallbacks(this)
        isRegisteredForLifecycleCallbacks = false
    }

    override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
        if (isStartedFromBackground || onCreateTime != 0L) {
            return
        }
        onCreateTime = System.currentTimeMillis()
        if (onCreateTime - appStartTime > START_SLOWEST_TIME) {
            isTooSlowToInitUI = true
        }
    }

    override fun onActivityStarted(activity: Activity) {
    }

    override fun onActivityResumed(activity: Activity) {
        if (isStartedFromBackground || isTooSlowToInitUI || atLeastOnTimeOnBackground) {
            unregisterActivityLifecycleCallbacks()
            return
        }
        if (activity is HomeActivity) {
            trace?.stop()
            trace = null

            if (isRegisteredForLifecycleCallbacks) {
                unregisterActivityLifecycleCallbacks()
            }
        }
    }

    override fun onActivityPaused(activity: Activity) {
    }

    override fun onActivityStopped(activity: Activity) {
    }

    override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
    }

    override fun onActivityDestroyed(activity: Activity) {
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onEnterBackground() {
        atLeastOnTimeOnBackground = true
        ProcessLifecycleOwner.get().lifecycle.removeObserver(this)
    }

    object StartFromBackgroundRunnable : Runnable {
        override fun run() {
            if (onCreateTime == 0L) {
                isStartedFromBackground = true
            }
        }
    }

}

4.在仪表板上添加自定义指标

在仪表板上,添加自定义指标 cold_startup_time。文章来源地址https://www.toymoban.com/news/detail-424312.html

到了这里,关于Android 应用启动时间统计方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 应用系统的日期和时间选择器

    一、日期选择期 二、时间选择器 三、遇到选择的取消和确认可以点击但是不显示的问题 由于某些原因按钮的字体颜色有时显示为白色 为了解决这个问题,我向 TimePickerDialog 添加了一个对话框主题来设置按钮文本颜色。 这是我添加到 styles.xml 的 xml 代码 关于android - TimePicke

    2024年02月07日
    浏览(55)
  • Android应用启动流程:从启动到可交互的过程解析

    关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 我们继续总结学习 Android 基础知识 ,温故知新。 还是在多年前做系统应用开发的时候,通过编译源码学习了一

    2024年02月11日
    浏览(45)
  • Android 源码解读-应用是如何启动的

    作者:Android帅次 作为多年的 Android 开发,写了不少应用,但是一个App到底是怎么启动起来的?你要说桌面点一下就启动了,那也对。但是它的启动过程呢?带着这样的疑问,咱们来一步步学习。 一般在任何平台上,都会逐步加载和执行以下组件: Boot loader U-boot (optional) Ke

    2024年02月02日
    浏览(36)
  • Android 打开其他应用的方式

    很多时候,我们会想打开第三方应用,比如广告中判断应用是否安装,如果安装就跳转该应用首页,未安装则去应用商店该应用详情页。 那么接下来就讲讲几种打开第三方应用首页的方案。 知道包名跳转有以下三种 代码如下 看方法名就可以知道 这里的intent是通过PackageMan

    2024年02月10日
    浏览(41)
  • Android10开机自动启动应用的权限配置

    在android8.0之前的系统,native层编译的 二进制xxx.bin文件可以直接放到init.rc中当成一个service,放到on init标签中用start xxx 来运行,只要内核设备树中设置selinux权限为SELINUX_PERMISSIVE模式(调试模式),都可以正常运行,不会报错误。但是在android8.1之后,android的系统分区结构发生变

    2024年02月11日
    浏览(49)
  • Unity Android Studio 设置自启动应用

    前言 最近有需求,需把Unity软件发布到android平台后开机启动应用,在网上查了很多资料,现整理如下 Unity部分 新建项目,平台设置为android   tips: 需要勾选Export Project以便于导入Android Studio ,使用Unity版本为2021.3.32f1 Android Studio部分  android studio环境配置相关就省略了,如有需要网上有

    2024年02月05日
    浏览(50)
  • 如何在Android设备上检查应用程序使用情况,包括使用时间

    你可能不知道自己花了多少时间在手机上。很可能你一天中有一半的时间都在盯着手机屏幕。如果你怀疑这一事实,你会很快核实的。在这篇文章中,我们将向你介绍如何在Android设备上检查应用程序的使用情况。 你使用时间最长的应用程序可能会消耗最多的电池。然而,有

    2024年02月07日
    浏览(56)
  • APP备案(Android) - 各应用平台对APP备案时间节点要求

    今年因 工业和信息化部 要求,Andorid各大厂商陆续发出通知,需要各应用公司及时进行 app备案 ,如过期未进行备案则会被陆续下架! 关联Blog APP备案(Android) - 各应用平台对APP备案时间节点要求 APP备案(Android) - 获取签名证书公钥、MD5 正好在统计 Andorid各平台 对于 app备案时间

    2024年01月20日
    浏览(53)
  • Android跳转具体应用权限管理,三种方式

    背景: Android越来越安全合规,在应用里,需要给用户所有可选择和取消的明确方式。 比如:设置了权限,也要给用户关闭权限的入口。被要求在应用的设置里,提供权限管理入口。 解决方式有三: 方式一:给每个手机厂商跳转做定制适配 有点费力,但是精准,如下:  

    2024年02月16日
    浏览(71)
  • Android应用启动时白屏或者黑屏处理办法

    老生常谈的问题了,随便记录一下吧。 通过设置主题来防止白屏或者黑屏 一般情况下,启动页面通常是全屏的,而且会用一张图片来展示用户打开应用程序后第一眼看到的界面。在手机中点击应用程序的图标到应用程序显示完MainActivity的视图这个过程中,通常会用一到两秒

    2024年02月10日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包