In the course of this series on running in the background, we’ve covered how to run a process in the background (Part One), how to move your application from foreground to background and vice versa (Part Two), and some of the reasons why you would want to (Part Three). The previous articles have shown Super App features that enable both the “Always-on Experience” and “Tight Integration with the Native Apps”, as well as a “Proactive and Notification-driven Application”. Today, the focus will be on “Designing for Efficiency”.
In some ways, the mobile environment is constrained much more significantly than the desktop environment, with limits to battery life, wireless bandwidth, memory, and CPU cycles, among others. These constraints become even more important when running processes in the background. The last thing the user wants is a massive data bill, or a dead device due to a poorly behaved background application that they weren’t even aware of. With that said, let’s look at the “dos and don’ts” of running in the background.
If you have any looped painting, animations, or other UI processes on your screen, stop them when your application moves to the background. Verify that you don’t have UI threads running needlessly by using the Profiler view in the BlackBerry® Java® Plug-in for Eclipse®.
As in checking for painting threads, use the Profiler to ensure that you don’t have threads running that aren’t actually necessary. A careful balance must be maintained here; if you perform an action in your application that may take some time, the application will expect it to continue even if you go to another application in the meantime. Similarly, if your application is expected to do tasks in the background – such as downloading music or tracking GPS coordinates – then processing can’t be avoided. However, battery life will be greatly enhanced if your application does this processing all at once, with periods of full idleness in between processing blocks. Ensure that your processing is not spread out over a long period of time, and the device will be able to go to a low-power sleep mode.
Be Aware of the Device Context
Before your application runs a background process, check the status of the device to determine if it is an appropriate time, or to optimize the task itself. Check the Idle Time using DeviceInfo.getIdleTime() and Backlight.isEnabled() to determine if you are currently using the device. Heavy processing should be done when the device is idle in order to avoid an impact to the user.
If the task your application intends to do is lengthy, ensure that there is adequate battery power available, or wait until the device is connected to a charging source. The DeviceInfo.getBatteryLevel() API will return the percentage of remaining battery, while DeviceInfo.getBatteryStatus() & DeviceInfo.BSTAT_CHARGING >0 will determine if the battery is currently charging. Applications should not keep the backlight on unless the device is connected to a charger, or if the screen display is critical to the application. For example, navigation apps should shut off the backlight when not powered by a car charger, while a video player should enable the backlight while the video is playing but not when it finishes.
Finally, check the network coverage available if you need to make a network connection, or the GPS satellite coverage if you intend to use GPS. If coverage is poor, then it will take more power to use the radio, or it may be more effective to wait until coverage is better. In the case of network communication, it may be more effective to download a smaller, lower quality set of data immediately and wait until WiFi® coverage is available, or to sideload large data through USB. For GPS, cell site location will provide approximate location with very low power use almost instantaneously while waiting for a more accurate GPS satellite fix to occur. The BlackBerry location object can provide information on the number of satellites visible to determine the effectiveness of getting a satellite fix. Likewise, the RadioInfo.getSignalLevel() API will tell you how strong the signal is, and the CoverageInfo.isCoverageSufficient() or TransportInfo.hasSufficientCoverage() methods will tell you if a connection is possible through the transport that you require.
Dropping references to stale objects is important when your application is long-lived. Objects should be released when no longer needed, but not too aggressively. Since object creation is costly, you don’t want to churn through objects if you will need them again, so there is a balance to find here. For example, your application should not usually release screens it has on the stack immediately upon going to the background. If you switch back to your application, you do not want to wait for the screen to be recreated. However, if the screen contains information from an external source, that data structure could be released when it’s no longer current and refreshed when you return.
Running in the background is a pillar of the Super Apps concept, and with so many Super App features enabled by background processing, it’s critical to remember to “Design for Efficiency”. You’ll earn the gratitude of your users – and they will enthusiastically recommend your app to their friends and colleagues!
Have you tried integrating any of these tips into your Super Apps designs? Let us know in the comments.