Skip to main content

ApplicationExitInfo

Android 11 (API Level 30) introduces a class named ApplicationExitInfo that contains the information of an application process's death.

This class is mostly useful for debugging crashes caused by Application Not Responding (ANR) (unresponsive) or native code crash. However, it can also be used to gain insight of why our application exits.

Basic Usage​

To use ApplicationExitInfo class, simply use getHistoricalProcessExitReasons() method inside ActivityManager class:

import android.app.ActivityManager
import android.app.ApplicationExitInfo
import android.content.Context
import android.os.Build
import android.util.Log
import java.io.File

val activityManager = context.getSystemService(ActivityManager::class.java)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val applicationExitInfos = activityManager.getHistoricalProcessExitReasons(
context.packageName,
0,
0,
)
applicationExitInfos.forEach {
Log.i("TAG", it.toString())
if (it.reason == ApplicationExitInfo.REASON_ANR || it.reason == ApplicationExitInfo.REASON_CRASH_NATIVE) {
// Copy trace stack to a temporary file
it.traceInputStream?.use { input ->
val file = File.createTempFile("tracestack", ".txt")
file.outputStream().use { output ->
input.copyTo(output)
}
}
}
}
}

Notice that for process deaths that caused by REASON_ANR and REASON_CRASH_NATIVE, we can try retrieving the stacktrace by using getTraceInputStream() method.

ApplicationExitInfo also has getReason() method that contains the reason code of the application process' death. Taken from the documentation, the possible reason codes are as follows:

Reason CodeDescription
REASON_ANRApplication process was killed due to being unresponsive (ANR).
REASON_CRASHApplication process died because of an unhandled exception in Java code.
REASON_CRASH_NATIVEApplication process died because of a native code crash.
REASON_DEPENDENCY_DIEDApplication process was killed because its dependency was going away, for example, a stable content provider connection's client will be killed if the provider is killed.
REASON_EXCESSIVE_RESOURCE_USAGEApplication process was killed by the system due to excessive resource usage.
REASON_EXIT_SELFApplication process exit normally by itself, for example, via System.exit(int); getStatus() will specify the exit code.
REASON_FREEZERApplication process was killed by App Freezer, for example, because it receives sync binder transactions while being frozen.
REASON_INITIALIZATION_FAILUREApplication process was killed because of initialization failure, for example, it took too long to attach to the system during the start, or there was an error during initialization.
REASON_LOW_MEMORYApplication process was killed by the system low memory killer, meaning the system was under memory pressure at the time of kill.
REASON_OTHERApplication process was killed by the system for various other reasons which are not by problems in apps and not actionable by apps, for example, the system just finished updates; getDescription() will specify the cause given by the system.
REASON_PACKAGE_STATE_CHANGE (🚨 New in Android 14)Application process was killed because the app was disabled, or any of its component states have changed without PackageManager.DONT_KILL_APP.
REASON_PACKAGE_UPDATED (🚨 New in Android 14)Application process was killed because it was updated.
REASON_PERMISSION_CHANGEApplication process was killed due to a runtime permission change.
REASON_SIGNALEDApplication process died due to the result of an OS signal; for example, OsConstants.SIGKILL; getStatus() will specify the signal number.
REASON_UNKNOWNApplication process died due to unknown reason.
REASON_USER_REQUESTEDApplication process was killed because of the user request, for example, user clicked the "Force stop" button of the application in the Settings, or removed the application away from Recents.
REASON_USER_STOPPEDApplication process was killed, because the user it is running as on devices with mutlple users, was stopped.

References​