Android Quick Tip: Testing Your App Being Killed in the Background

Written by: on October 2, 2017

Of the several steps of the Android Activity Lifecycle, onDestroy() can be one of the more frustrating. Ideally, it’s called whenever your activity is killed. This can happen when you call finish() on your Activity. However in some other cases where your app is killed while not visible to the user, onDestroy() may not be called. Despite the name implying it is always the last thing to get called when your app is destroyed, it’s not really a suitable spot to do some of your last minute cleanup.

A common scenario for an app getting killed in the background is when Android does so to gain access to more memory. Consider a user that has left your app to use other more memory-intensive apps, perhaps to read a pdf and or stream some video. In that case, it’s possible that Android needed to kill your app’s process to make more memory available. In this case, explained in the Android documentation, your app won’t have onDestroy() called. The inconsistency of onDestroy() means most of your teardown operations should be done in onStop(), which is always called when your activity is no longer visible to the user.

This cleanup is a very important step for preventing memory leaks. Holding on to heavy resources, such as media players or other threads, can lead to performance issues on your user’s device. How do you test this possibility and ensure you’re handling your app being killed in the background? There are a few ways to do it depending on the tools available to you.

Android Monitor

Android Studio and previous Android framework plugins have long featured the Android Device Monitor. This view surfaces a lot of functionality from adb and the shell without the need to open up the command line or worry about getting root access to your device.

You can open up the Android Device Monitor from Android Studio with Tools > Android > Android Device Monitor. From there, you’ll want to show the DDMS” perspective. The DDMS, or Dalvik Debug Monitor Server, is a powerful tool that can be used for performance monitoring and debugging. You can find more information on what else it can do here.

Once you have DDMS open, take a look at the Devices tab. Here, you should see all devices you have plugged in, as well as a list of all processes you have can observe and control. This view serves the same purpose as the ps command explained above. Once you’ve found your process, killing it is as simple as clicking the “STOP” icon at the top of the view.

This is the quickest and easiest way to accomplish this if you have access to this tool. But perhaps you’re on a QA team that doesn’t have Android Studio. There are a few helpful command-line tools that can help you test how your app responds to its process being killed by Android, and how your app behaves when resuming.

ADB & The Command Line

First you’ll need to plug in your Android device and connect to its shell using adb shell. If you’re unfamiliar with using the android shell, the Android Docs for ADB has a great section on this.

Listing the Running Processes

The first command we’ll cover is ps, which dumps a list of all processes currently being run on your device. Additionally, you can filter the results by piping the result to grep. In the below example, I have a simple demo app shown on screen. Then I open my devices shell, and filter ps by fooblah, which is part of the package name of the demo app. Since there are a huge number of processes running on a device at any time, this filtering step will help in finding your app amongst the rest.

Killing the Process

Since Android will sometimes kill a process when it is memory starved, you can get this to happen by doing memory-intensive stuff on your device (video streams, big images, etc.), and intermittently check “ps” to see if your process has been killed yet. This can be pretty time consuming, but should work on any Android device given enough time/memory usage. Luckily, we have a tool to speed this up, the activity manager. This tool surfaces a huge amount of functionality around Activities through the am command. We’ll be using it to kill our process. This simulates the same thing Android does when it needs more memory. In the below example, the demo app was shown, and then the user pressed home. We run the “ps” command as before to confirm our process has not yet been killed. Then, we’ll use am kill {package_name} with the package name of the app to “kill all processes associated with package […]. This command kills only processes that are safe to kill and that will not impact the user experience” (Android Studio Documentation). After that, we can run ps again, but this time, the demo app does not appear.

Another command you can use to kill a process is am force-stop.It similarly kills the background process, but doesn’t have the same restrictions on it not affecting the user. While both of these commands can work, they’re not guaranteed to. This inconsistency is caused by hardware providers modifying how their version of Android handles these events. For example, Amazon’s Android fork for Fire TV allows am kill to work, but not am force-stop.

Sometimes neither am force-stop nor am kill work, which adds some extra steps for the person testing, but ps should always work, so manually using a lot of memory is still an option.

While finding the best way to test this use-case can take some trial and error, testing this flow is very much worth it. Error dialogs being shown while your app isn’t even visible or as soon as it’s resumed will earn you a one-way ticket to being uninstalled. As our QA team says, you need to test everything you expect your user to do, so make sure your app can be paused and resumed seamlessly with this now easy step!

Joshua Lamson

Joshua Lamson

Joshua Lamson is a Software Engineer at POSSIBLE Mobile, specializing in Android Development. Joshua is a graduate of the Colorado School of Mines and has an affinity for rubik's cubes.
Article


Add your voice to the discussion: