ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Follow publication

Analyzing App Startup and Shutdown details in Android 15

Tomáš Repčík
ProAndroidDev
Published in
5 min readOct 17, 2024

--

ApplicationStartInfo

val activityManager: ActivityManager =
context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val startInfos = activityManager.getHistoricalProcessStartReasons(maxNumberOfInstances)

Available data:

val startType = startInfo.startType
val startReason = startInfo.reason
val startUpState = startInfo.startupState
val launchMode = startInfo.launchMode
val startTimestamp = startInfo.startupTimestamps
val wasForceStopped = startInfo.wasForceStopped()
val startIntent = startInfo.intent

Add callback

val executor = context.mainExecutor
activityManager.addApplicationStartInfoCompletionListener(executor) {
// access the ApplicationStartInfo via `it`
}

Add your events

val currentTimeInNanos = System.nanoTime()
activityManager.addStartInfoTimestamp(25, timestamp)

ApplicationExitInfo

val exitInfos = activityManager.getHistoricalProcessExitReasons(packageName, 0, maxNum)

Available data:

Example usage

enum class StartReason {
START_REASON_ALARM,
START_REASON_BACKUP,
START_REASON_BOOT_COMPLETE,
START_REASON_BROADCAST,
START_REASON_CONTENT_PROVIDER,
START_REASON_JOB,
START_REASON_LAUNCHER,
START_REASON_LAUNCHER_RECENTS,
START_REASON_OTHER,
START_REASON_PUSH,
START_REASON_SERVICE,
START_REASON_START_ACTIVITY;

companion object {
fun fromValue(value: Int): StartReason = when (value) {
ApplicationStartInfo.START_REASON_ALARM -> START_REASON_ALARM
ApplicationStartInfo.START_REASON_BACKUP -> START_REASON_BACKUP
ApplicationStartInfo.START_REASON_BOOT_COMPLETE -> START_REASON_BOOT_COMPLETE
ApplicationStartInfo.START_REASON_BROADCAST -> START_REASON_BROADCAST
ApplicationStartInfo.START_REASON_CONTENT_PROVIDER -> START_REASON_CONTENT_PROVIDER
ApplicationStartInfo.START_REASON_JOB -> START_REASON_JOB
ApplicationStartInfo.START_REASON_LAUNCHER -> START_REASON_LAUNCHER
ApplicationStartInfo.START_REASON_LAUNCHER_RECENTS -> START_REASON_LAUNCHER_RECENTS
ApplicationStartInfo.START_REASON_OTHER -> START_REASON_OTHER
ApplicationStartInfo.START_REASON_PUSH -> START_REASON_PUSH
ApplicationStartInfo.START_REASON_SERVICE -> START_REASON_SERVICE
ApplicationStartInfo.START_REASON_START_ACTIVITY -> START_REASON_START_ACTIVITY
else -> throw IllegalArgumentException("Unknown start reason value: $value")
}
}
}
data class StartupTimestamps(
val applicationOnCreate: Long? = null,
val bindApplication: Long? = null,
val firstFrame: Long? = null,
val fork: Long? = null,
val fullyDrawn: Long? = null,
val initialRenderThreadFrame: Long? = null,
val launch: Long? = null,
val reservedRangeDeveloper: Long? = null,
val reservedRangeDeveloperStart: Long? = null,
val reservedRangeSystem: Long? = null,
val surfaceFlingerCompositionComplete: Long? = null
) {
companion object {
fun fromMap(timestampMap: Map<Int, Long>): StartupTimestamps = StartupTimestamps(
applicationOnCreate = timestampMap[ApplicationStartInfo.START_TIMESTAMP_APPLICATION_ONCREATE],
bindApplication = timestampMap[ApplicationStartInfo.START_TIMESTAMP_BIND_APPLICATION],
firstFrame = timestampMap[ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME],
fork = timestampMap[ApplicationStartInfo.START_TIMESTAMP_FORK],
fullyDrawn = timestampMap[ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN],
initialRenderThreadFrame = timestampMap[ApplicationStartInfo.START_TIMESTAMP_INITIAL_RENDERTHREAD_FRAME],
launch = timestampMap[ApplicationStartInfo.START_TIMESTAMP_LAUNCH],
reservedRangeDeveloper = timestampMap[ApplicationStartInfo.START_TIMESTAMP_RESERVED_RANGE_DEVELOPER],
reservedRangeDeveloperStart = timestampMap[ApplicationStartInfo.START_TIMESTAMP_RESERVED_RANGE_DEVELOPER_START],
reservedRangeSystem = timestampMap[ApplicationStartInfo.START_TIMESTAMP_RESERVED_RANGE_SYSTEM],
surfaceFlingerCompositionComplete = timestampMap[ApplicationStartInfo.START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE]
)
}
}
enum class ExitReason {
REASON_ANR,
REASON_CRASH,
REASON_CRASH_NATIVE,
REASON_DEPENDENCY_DIED,
REASON_EXCESSIVE_RESOURCE_USAGE,
REASON_EXIT_SELF,
REASON_FREEZER,
REASON_INITIALIZATION_FAILURE,
REASON_LOW_MEMORY,
REASON_OTHER,
REASON_PACKAGE_STATE_CHANGE,
REASON_PACKAGE_UPDATED,
REASON_PERMISSION_CHANGE,
REASON_SIGNALED,
REASON_UNKNOWN,
REASON_USER_REQUESTED,
REASON_USER_STOPPED;

companion object {
fun fromValue(value: Int): ExitReason = when (value) {
ApplicationExitInfo.REASON_ANR -> REASON_ANR
ApplicationExitInfo.REASON_CRASH -> REASON_CRASH
ApplicationExitInfo.REASON_CRASH_NATIVE -> REASON_CRASH_NATIVE
ApplicationExitInfo.REASON_DEPENDENCY_DIED -> REASON_DEPENDENCY_DIED
ApplicationExitInfo.REASON_EXCESSIVE_RESOURCE_USAGE -> REASON_EXCESSIVE_RESOURCE_USAGE
ApplicationExitInfo.REASON_EXIT_SELF -> REASON_EXIT_SELF
ApplicationExitInfo.REASON_FREEZER -> REASON_FREEZER
ApplicationExitInfo.REASON_INITIALIZATION_FAILURE -> REASON_INITIALIZATION_FAILURE
ApplicationExitInfo.REASON_LOW_MEMORY -> REASON_LOW_MEMORY
ApplicationExitInfo.REASON_OTHER -> REASON_OTHER
ApplicationExitInfo.REASON_PACKAGE_STATE_CHANGE -> REASON_PACKAGE_STATE_CHANGE
ApplicationExitInfo.REASON_PACKAGE_UPDATED -> REASON_PACKAGE_UPDATED
ApplicationExitInfo.REASON_PERMISSION_CHANGE -> REASON_PERMISSION_CHANGE
ApplicationExitInfo.REASON_SIGNALED -> REASON_SIGNALED
ApplicationExitInfo.REASON_UNKNOWN -> REASON_UNKNOWN
ApplicationExitInfo.REASON_USER_REQUESTED -> REASON_USER_REQUESTED
ApplicationExitInfo.REASON_USER_STOPPED -> REASON_USER_STOPPED
else -> throw IllegalArgumentException("Unknown exit reason value: $value")
}
}
}

Android development

23 stories

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Published in ProAndroidDev

The latest posts from Android Professionals and Google Developer Experts.

Written by Tomáš Repčík

https://tomasrepcik.dev/ - Flutter app developer with experience in native app development and degree in biomedical engineering.

No responses yet

Write a response