Arne Stockmans.be

Blog - About - Contact

Exploring the Android 11 App Exit Reasons API

Previous Thursday, Google released Android 11 Developer Preview 3. One of the updates was in the "Exit reasons API". This API will give you - like the name suggests - the reasons why your app has exited. And not only the reason, but also some more information. Let's have a look!

Exploring the API

You can get a list of ApplicationExitInfo objects, by calling getHistoricalProcessExitReasons on the ActivityManager. There are three arguments you have to pass: packageName, pid, and maxNum.

  • packageName: A nullable parameter, to specify from which package you want to fetch the exit reasons. Pass null for your current app. You need the DUMP permission to fetch exit reasons for other packages, which isn't available for third-party apps.
  • pid: A process ID that used to belong to this package but died later. A value of 0 means to ignore this parameter and return all matching records.
  • maxNum: The maximum number of results to return. A value of 0 means to ignore this parameter and return all matching records.
val activityManager: ActivityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val exitReasons = activityManager.getHistoricalProcessExitReasons(/* packageName = */ null, /* pid = */ 0, /* maxNum = */ 5)

// exitReasons = [ApplicationExitInfo(timestamp=4/25/20, 3:50 PM pid=5102 realUid=10147 packageUid=10147 definingUid=10147 user=0 process=be.gekrabbel.exitreasons reason=10 (USER REQUESTED) status=0 importance=100 pss=34MB rss=117MB description=stop be.arnestockmans.exitreasons due to from pid 5163 state=empty trace=null]

As you can see in the previous code snippet, I fetch the latest 5 exit reason of the current app. This returns a list of ApplicationExitInfo objects, sorted from the most recent to the oldest known exit. These objects contains some interesting properties, for example: timestamp, reason, importance, description, and trace.

  • timestamp: Like the name suggests - when the app exited.
  • reason: A number which refers to one of the reason constants.
  • importance: How important the process was when it exited.
  • description: A readable description of what happened. Only useful for debugging purposes, not to display to a user.
  • trace: The traces that were taken before the death of the process, only used when the app exited due to an ANR.

There are more properties to inspect, but these 5 are in my opinion the most interesting. So, now that we know which information we can request, we can think of possible use cases for this API!

Oops, Something went wrong

We can detect if the user exited the app because of a crash. You will see the details of the crash in the Google Play Console. Besides that, you can see even more details if you use third-party services like Crashlytics or Sentry. They will alert you that there's an issue with your app, but that's not something your users are aware of. This new API gives us an opportunity to apologise to the user, and comfort them by saying we're aware of the issue.

So how do we know our app has exited ungracefully? Well, we can check the reason parameter. The possible constants to check against are:

  • REASON_ANR
  • REASON_CRASH
  • REASON_CRASH_NATIVE
  • REASON_DEPENDENCY_DIED
  • REASON_EXCESSIVE_RESOURCE_USAGE
  • REASON_EXIT_SELF
  • REASON_INITIALIZATION_FAILURE
  • REASON_LOW_MEMORY
  • REASON_OTHER
  • REASON_PERMISSION_CHANGE
  • REASON_SIGNALED
  • REASON_UNKNOWN
  • REASON_USER_REQUESTED
  • REASON_USER_STOPPED

As you can see, there are several reasons why your app can exit. And not all of them are because of an issue with your app. For example: if the reason is REASON_USER_REQUESTED your app didn't crash - it exited because the user closed it. By the way, note that simply pressing back doesn't really close the app. So this doesn't create a new entry in the list of app exit reasons; it will only create a new entry when your app's process gets killed. So if your user closes your app by pressing back or home, and immediately reopens it, it isn't considered an exit. But if your user closes the app, and doesn't reopen it immediately, it's process will get killed after a while, which will add a new ApplicationExitInfo entry.

Here's what you've missed

Another interesting property is timestamp. It gives us the unix timestamp in milliseconds when the app exited. We can use it to analyse how often our app is used, and if we can notice any patterns in this. But to keep it simple, we could also show a simple "Welcome back" message. Maybe we can even give a small recap of what happened since the user's last visit.

On a final note, this post is written right after Developer Preview 3 was released. This feature is still under development, and can possibly change in later releases. Google also asks for feedback on this feature, so feel free to let them know what you think of it.

© 2020 Arne Stockmans, Built with Gatsby