Thinking Beyond Your Android Application Boundaries
At times, the Android device may perform extraneous work that can affect your application, such as downloading a large file in the background while playing music from an online radio application. Will these heavy network-bound activities affect the application in any way? It depends.
If your app needs a connection to the Internet and for some reason cannot connect, will it crash? What will happen? Knowing the answers to these questions means that you’re thinking beyond your application boundaries.
Not all apps are created equal — some good ones are out there, along with some bad ones. Before building or releasing your first Android application, ensure that you know the ins and outs of your application and anything that can affect it. Be sure that the app doesn’t crash when users perform routine tap events and screen navigation.
Building applications on embedded devices is very different than building them on a PC or Mac, and the reason is simple: The resources (battery, memory and processor, for example) are limited. If the Android device is a phone, its main purpose is to perform phone-like duties, such as recognizing an incoming call, maintaining a signal, and sending and receiving text messages.
If a phone call is in progress, the Android system treats that process as vital, whereas a downloading file in the background is considered non-vital. If the phone starts to run out of resources, Android kills all non-vital processes to keep the vital ones alive. A file can be downloaded again, but when a call is lost, it’s lost forever — you have to make that call again, which would only frustrate the user if the main purpose for purchasing the device was to have a phone.
Your app might download a file in the background and the process gets killed — this is a scenario that you need to test. It can also happen if your phone encounters an area with a poor or non-existent wireless signal. If the connection gets dropped, your file isn’t downloaded.
Test for all possible solutions and have a safety guard for them. Otherwise, your app will be prone to runtime exceptions, which can lead to poor reviews from users at the Google Play Store.
Interacting with your application
To ensure that your app works, fire it up and play with its features. While your app is running, start another app, such as the browser. Visit a few sites, and then return to your app. Click any buttons related to your app to see what happens. Try all kinds of things to see whether you find outcomes that you didn’t consider.
What happens if a user is interacting with your app and receives a phone call? Are you saving the necessary state in onPause() and restoring it in onResume()?
Android handles the difficult task management for you, but it’s ultimately your responsibility to manage the state of your application.
The most common errors come from Android developers failing to save their state properly in onPause and restore it in onResume. Remember that Android can kill your activity at any time, and it’s up to you to make sure you properly save your activity’s state so it can be re-created later if necessary!
Testing whether your application works
In the emulator or on your device, open the Silent Mode Toggle application from the launcher. You’ve already performed the first step in the testing process — making sure that the app starts!
After the app is open, check to see whether the phone is in Silent mode by looking for the small star icon on the notification bar.
Click the Silent Mode Toggle button to toggle the ringer mode. Did the application’s image change? Try various actions to ensure that your application works as expected. If you find a flaw, use the debugging tools featured in this chapter to help identify the issue.
Are you having difficulty turning Silent mode off again? You may have been hit by a bug introduced in Android 5.0.
What about automated testing?
With the rise of agile methodologies over the past decade, it’s only a matter of time before you start to wonder how to perform automated testing in Android. The SDK installs Android unit-testing tools that you can use to test not only Java classes but also Android-based classes and user interface interactions.
Here are some tools at your disposal:
JUnit: The Android SDK includes JUnit 3.x integration. You can use JUnit, a popular unit-testing framework that’s used in Java, to perform unit testing or interaction testing, and you can find more information about JUnit. To make your development life easier, Android Studio has built-in tools to help facilitate testing in JUnit through Android Studio.
Monkey: The user interface and application exerciser known as Monkey runs on your emulator or device and generates pseudorandom streams of user events, including taps, gestures, touches, clicks, and a number of system events. Monkey, which is installed with the Android SDK, is a helpful way to stress-test an application.
UI Automator: The UI Automator testing framework lets you test your user interface (UI) efficiently by creating automated functional UI test cases that can be run against your app on one or more devices.
Espresso: The Espresso library makes unit testing Android significantly easier than using straight JUnit. It uses a simple and concise style to write Android unit tests. Beginning with 2.0, Espresso is now distributed as part of the Android SDK.