Efficient

The other chapters in this guide describe how to implement five of the features and characteristics of Super Apps in your application. For BlackBerry® device users to enjoy using your application on a daily basis and recommend it to others, you should implement these features efficiently.

An efficient application takes into consideration the limited resources of a mobile device, such as processor power, battery life, and memory, and uses these resources as effectively as possible. An efficient application doesn't consume battery power too quickly, open unnecessary network connections that might increase a user's wireless data charges, or make the UI on the BlackBerry device sluggish or unresponsive.

Remember that users don't usually report or provide feedback on performance issues with applications; they typically delete these applications from their devices. For this reason, it's important to focus on creating efficient Super Apps.

What are the benefits of an efficient application?

Increase battery life. A longer battery life means that users can spend more time using your application and less time charging their devices or searching for applications to remove to improve performance (including yours!).

Improve response times. Efficient applications can respond quickly to a user's input, which means less waiting on the user's part and more potential for productivity.

Reduce data costs. Users don't want to see an increase on their bill from their wireless service provider because your application is transferring data unnecessarily. If your application transfers very little data while it's in use, your users are more likely to continue to use your application and recommend it to others.

Increase the "stickiness" of your application. A "sticky" application is one that a user sticks with, that engages the user, that the user comes back to over and over again. By focusing on efficiency when you design your application, you can improve your user's experience and help increase the stickiness of your application.

Approaches to efficient application design

You can help make your application efficient by using any of the following approaches.

Approach

Examples

Be aware of the status of the BlackBerry® device (such as battery power level, network connectivity, and so on) and respond accordingly.

If your application is designed to download songs or videos from a website, your application should stop downloading content if the battery level or available memory on the device is low.

Download large files only when the device is connected to a Wi-Fi® network.

Eliminate or defer unnecessary processing on the device.

If your application needs to perform complex calculations, perform these calculations when the device is idle.

Have data such as news items, status updates, or other data pushed to the device periodically instead of having the device poll to retrieve the data.

Use location services, such as GPS and geolocation, carefully.

If your application needs to obtain a GPS fix, perform full scans of the sky to locate satellites for the fix only when necessary.

Use assisted GPS mode sparingly.

Use the Profiler tool to optimize your code.

Find out what methods in your application take the most time to run, and try to optimize these methods.

Determine how many objects your application creates while it's running, and try to reduce this number if possible.

Responding to the status of the device

The Highly contextualized chapter describes how to
consider the contexts (such as battery, connectivity, and device characteristics) that are associated with BlackBerry® devices.
When you design your application, the monitoring of certain contexts, or states, of the
device can help your application be more efficient while also
providing an exceptional user experience. Your application can detect states
such as low battery level, poor wireless coverage, and Wi-Fi® connectivity
to increase efficiency.

You can change the behavior of your application
in response to state changes. For example, the
Bookshelf application communicates with a web service that provides
information about books that have been released. If Bookshelf
detects that the device is connected to a Wi-Fi network, Bookshelf can use the bandwidth that the Wi-Fi connection provides to request more
detailed information about a book, such as cover art, audio clips,
and extended synopses.

Using listeners

One of the most effective ways to respond to state changes on a device
is by using listeners. You can register your application as a
listener for different types of events. You might want your
application to close automatically if the battery level reaches a
certain point, or to provide different options if the device is
connected to a computer using a USB connection. You can also use
listeners to monitor global events on the device and use these
global events to communicate between processes.

To be enabled as a listener, your application must implement one
or more listener interfaces (for example, CoverageStatusListener or
GlobalEventListener). The following table describes some
common listener interfaces and the events that they listen for.

You can use this listener to determine when the amount of available memory is low.

If you choose to use listeners in your application, it's
important to remember to deregister the listeners that you use when
you are done with them. If you don't deregister a listener, a
reference to the listener remains in memory on the device, and your
application is not properly terminated.

You can create your own listeners if the ones that are provided
in the BlackBerry APIs don't suit your needs. This approach might
be a good way to improve the efficiency of your application. A
listener that you create yourself might be more focused or
specialized for your application's functionality than a generic
listener. For example, a listener that is designed for the Bookshelf application might listen specifically for events that are
generated by the Bookshelf web service, such as when new
information about a book's location is available.

Checking the status of the device

Your application can check the status of the device before
trying to perform a particular action. For example, you can invoke
DeviceInfo.getBatteryLevel() or DeviceInfo.getBatteryStatus()
before you start your application, to determine if there is
sufficient battery power remaining to run your application or to
perform a lengthy operation. You can also invoke
DeviceInfo.getIdleTime() to determine how long the device has been
idle, which is useful when you want your application to perform
complex or time-consuming operations when the user is not using the
device.

If your application must open a network connection, your
application should check the network coverage that is available. If
coverage is poor, your application uses more battery power to use the
wireless transceiver on the device, and a more efficient approach might be
to wait until coverage improves to open the connection.
Alternatively, you can design your application to retrieve a
smaller, lower-quality set of data immediately, and then wait until
coverage improves or a Wi-Fi connection is available to retrieve
the full set of data. You can invoke RadioInfo.getSignalLevel(),
CoverageInfo.isCoverageSufficient(), or
TransportInfo.hasSufficientCoverage() to help you determine the
available network coverage.

You should also consider whether an IT policy
rule that is set by a BlackBerry® Enterprise Server administrator
might block a feature of the device that your application is trying
to use. For example, if the Disable GPS IT policy rule is applied
to the device, your application won't be able to obtain a GPS fix
and should not waste resources trying to do so.

Code sample: Listening for status changes to the wireless coverage

The following code sample demonstrates how you can listen in your application for
status changes to the wireless coverage. Your application can respond and stop transferring data or
communicating with a server or web service.

Code sample: Setting a listener when the backlight changes

The following code sample demonstrates how you can set a
listener in your application when the backlight changes on the device. If the
backlight is off, your application doesn't need to respond to any
events, and you don't need to set a listener for the screen. If
the backlight is on, your application can resume listening for
events.

Code sample: Detecting a low battery level on a device that is not charging

The following code sample demonstrates how you can detect a low battery level on a device that is not charging. If this
situation occurs, you might want to close your
application automatically or stop using GPS.

Eliminating unnecessary processing on the device

The Always on chapter describes how to keep your
application running in the background on a BlackBerry® device, as
well as how to schedule processes to run periodically. When you
implement these approaches correctly, you build efficiency into
your application by choosing when and how often to perform
processing.

You can help make your application efficient by minimizing the
amount of processing that you need to do in your application, and
eliminating any processing that might not be necessary at a given
time. For example, the Bookshelf application doesn't need to check
the Bookshelf web service continuously for updates to the
information about a book. A book's information doesn't change very
often, so it might be more efficient to use a push solution to send the updates to Bookshelf when the information is updated.

Running in the background

You should only run your
application in the background if it makes sense to do so. Running your application in the background lets
your application continue to process data and provide updates to
the BlackBerry device user, even when the user is using other applications on the
device. However, running in the background can consume valuable
system resources and battery power. There are alternatives to running your application in the
background:

You can push important information or updates to your application from an external source, such as a web server. Your application doesn't need to be running in the background to receive push notifications. When push data arrives on the device, if your application is registered as a push handler, your application processes the data automatically.

You can schedule processes to run periodically. Your application can perform resource-intensive operations at specific times so that your application doesn't run continuously.

When your application must perform tasks in the background, you
can save battery power by making sure that your application does
its processing all at once, instead of spread out over a long
period of time. The device
can enter a low-power mode when processing is complete to minimize
power consumption. You
should also avoid opening many separate network connections to transfer
small amounts of data. Instead, you should design your application
to wait until there is a significant amount of data to transfer,
and then open a single connection and transfer all of the data at
once.

Detecting when your application is not displayed

If your application includes any animations or contains code
that repaints the screen at regular intervals, you can save a
substantial amount of battery power by not redrawing UI elements if
your application is running but not displayed, or if your application is not in use. You can use the
following methods to determine if your application is in use:

You can use methods to stop animating or repainting the screen when the screen is not visible, and resume when the screen is visible again. You can override Screen.onExposed(), which is invoked when your application's screen is on top of the display stack and displayed to the user. You can override Screen.onObscured(), which is invoked when your application's screen is not displayed to the user or is obscured by another screen.

To determine if your application is in the foreground, you can invoke Application.isForeground(). If this method returns false, your application is not visible to the user.

To determine if the backlight on the device is turned on, you can invoke Backlight.isEnabled(). If this method returns false, no UI elements are visible to the user. The backlight turns off automatically after a period of inactivity. Your application should not keep the backlight on unless the device is connected to a charger, or if screen visibility is critical to the application.

To determine how long the device has been idle, you can invoke Device.getIdleTime(). To prevent any potential UI lag or latency, your application should perform processor-intensive operations when the device is idle.

Find out more

For more information about pushing content to devices, visit the following resources:

Using location services effectively

The Highly contextualized chapter describes how location
is an important context to consider when you're designing your
application. You can use GPS technology on the BlackBerry® device to
add this context to your application, but you should remember that
obtaining GPS fixes can consume a lot of battery power.

You can help make your application efficient by making effective
use of location services on the device, such as GPS and geolocation. For example, the Bookshelf application
should notify BlackBerry device users when they are in the area of a released book.
Because maintaining a GPS fix at all times can consume battery
power, Bookshelf might obtain a GPS fix only
periodically, with an option for more frequent fixes that the user
can select. Bookshelf might also use the geolocation service to
obtain the general position of the user until a more precise GPS
fix is calculated.

Obtaining GPS fixes that are timely and necessary

In general, the most battery-intensive operation when your application uses GPS on a device
is performing a full scan of the sky. A full scan of the sky involves locating and connecting to GPS satellites and obtaining a GPS fix using the information from those satellites. An application that performs
full scans frequently can drain the battery very quickly. To avoid this situation, your application should perform a full scan to obtain GPS fixes only as often as required to provide a good user experience. For example, your application might not need to maintain the user's exact position at all times, but instead can provide a good user experience if the application obtains a fix every ten minutes. If your application needs to track the user's position more precisely, you can decrease the time between fixes, at the cost of increased battery usage.

If your application cannot obtain a GPS fix, you should consider
carefully whether to retry the request. For example, if your application hasn't been
able to obtain a fix for the last 30 minutes, it might be because the
user is indoors, and your application shouldn't retry the request. Your application might also reduce the frequency of fix requests until a fix is successful.

Your application should use assisted GPS mode sparingly. Assisted GPS
mode obtains a GPS fix by communicating with the wireless service
provider to retrieve satellite information. This method
provides a fix very quickly and consumes less battery power than other GPS modes, but it relies on the wireless service
provider and increases their costs, as well as any network costs
that are associated with communicating with the wireless service
provider. You should design your application to use assisted GPS mode to obtain an initial fix before switching to autonomous
GPS mode. If you want your application to obtain a fix
using a particular GPS mode (for example, assisted GPS or autonomous
GPS), your application should check to see if that mode
is available by invoking GPSInfo.isGPSModeAvailable().

Using the geolocation service to obtain an approximate location

As an alternative to using GPS on a device, you can use the
geolocation service to retrieve the location of the device. The
geolocation service provides an approximate location (within 200
meters to 5 kilometers) and includes the latitude, longitude, and
horizontal accuracy based on the positioning of cell towers and
WLAN access points. If your application doesn't require the user's
exact position, the geolocation service can be an excellent
approach and can save substantial amounts of battery power. The
geolocation service can also function indoors, making it feasible
to use in applications that don't always have access to GPS
satellites (for example, applications that recommend local points
of interest).

Code sample: Using the geolocation service to obtain an approximate location

The following code sample demonstrates how to use the geolocation service to retrieve the approximate location of the device.

Using the Profiler tool

This chapter describes best practices for making your
application more efficient. This chapter describes how to respond to the
status of the BlackBerry® device, minimize or eliminate
unnecessary processing in your application, and use GPS
effectively to save battery power. You should also consider
code-level efficiency when you're designing your application. You
can make sure that the methods in your application run as
quickly and efficiently as possible, don't create too many objects,
and don't commit too many objects to memory on the
device. For example, if the Bookshelf application creates a new
object every time the application receives new location information
for a book from the Bookshelf web service, Bookshelf probably isn't
using objects as efficiently as it could. It might be more
efficient to update the same object each time with new information.

You can use the Profiler tool to analyze and optimize your code
for efficiency. The Profiler tool is available in the BlackBerry® Java® Development Environment or the BlackBerry® Java® Plug-in for
Eclipse®. You can use the Profiler tool to identify what threads
are running at any point in the execution of your application, how long methods take to run, how many objects your application creates, and so on.

When you're using the Profiler tool to analyze your code, the
values that you obtain (for example, execution time in clock ticks or execution
time in milliseconds) are most useful when considered
relative to each other. For example,
the number of clock ticks that one method takes to run isn't
necessarily relevant, because this number can vary depending on
factors such as device model, number of other applications running
simultaneously, whether the method is running on a device or on a
simulator, and so on. Instead, the comparison of the number of clock ticks
that two methods that perform the same function take is
more useful, and you can use this data to determine
which method is more efficient.

In general, you shouldn't try to reduce profiler metrics
individually. Instead, you should use these metrics to help identify areas of
inefficiency in your application. You can also use profiler metrics to
identify bottlenecks in your application's execution, and determine
the best places to try to optimize your code.

You should try to optimize the methods in your
application that run the most frequently, such as implementations of methods that open and manage network connections and methods that
draw UI elements (for example, Screen.paint(), Screen.paintBackground(),
and FullScreen.sublayout()).

The following table lists some of the metrics that you can monitor by using the Profiler
tool.

Metric

Description

Time spent in methods

You can determine the percentage of application execution time that was spent in each method in your application. If you have two methods that perform similar tasks, but one method takes substantially less time to run, you should examine the methods for opportunities to optimize the slower method.

You can perform this type of profiling on a BlackBerry Smartphone Simulator only.

Samples

You can determine what your application is doing at any point during execution. Approximately every ten milliseconds, the Profiler tool queries your application, and your application responds with a stack trace (a sample). The higher the number of samples for a method, the longer that method is taking to run. If a method produces a large number of samples relative to other methods in your application, this method might be a candidate for optimization.

You can perform this type of profiling on both a BlackBerry Smartphone Simulator and a device.

Objects created

You can determine how many objects your application creates during execution. Object allocation and garbage collection are the primary reasons for UI lag or latency in an application, so if a method creates a large number of objects relative to other methods in your application, you should examine the objects to determine if they are all required. Your application should reuse objects whenever possible.

You can perform this type of profiling on a BlackBerry Smartphone Simulator only.

Objects committed

You can determine how many objects your application writes to memory on the device during execution. Committing objects to memory is an expensive operation (in terms of execution time), so you should minimize these operations whenever possible. If your application must commit objects to memory, make sure that the objects are grouped so that they can be committed at the same time, instead of individually. Your application should also commit objects at the end of a full transaction or event.

You can perform this type of profiling on a BlackBerry Smartphone Simulator only.

Find out more

For more information about the Profiler tool, visit the following resources:

Storing data on the device

The Social and connected chapter describes how to capture audio and video in your application by using the javax.microedition.media.Player class. In the code samples in that chapter, the audio and video files are stored in internal storage on the BlackBerry® device by specifying a record location of file:///Store/... You can choose from several data storage options to store data or files that your application creates. Each storage option has advantages and disadvantages, and you should carefully consider which option to use based on the type of data that your application needs to store.

You can help make your application efficient by choosing the most appropriate storage location and storage option for your application's data. For example, the Bookshelf application needs to store information about a book that you have released, such as comments about the book or the book's current location. Storing this information on the device is probably more efficient than querying the Bookshelf web service whenever the user requests this information. If the information consists of relational data, you might choose to store the information in a SQLite® database. If the information needs to be shared between applications on the device, you might choose to store the information in the runtime store.

Understanding data storage options

The following table describes the main data storage options that you can use to store information that your application creates.

Data storage option

Description

File system

You can use this data storage option to create and manage the files and folders on a BlackBerry device or on an external media card by using the File Connection API. The File Connection API is implemented in the javax.microedition.io.file package.

Files that your application creates on a file system are not removed automatically when your application is removed from the device.

SQLite

You can use this data storage option to create and use SQLite relational databases by using the Database API. SQLite databases require no configuration or administration and are very small (around 300 KB). You can create SQLite databases in internal storage or on an external media card.

SQLite databases that your application creates are not removed automatically when your application is removed from the device.

Persistent store

You can use this data storage option to save objects in persistent memory on the device by using the Persistent Store API. Data is stored as PersistentObject objects, and these objects are retained in memory after the device restarts.

PersistentObject objects that your application defines are removed automatically when your application is removed from the device.

MIDP RMS

You can use this data storage option to save data in persistent memory by using the MIDP RMS. The MIDP RMS is modeled after a simple record-oriented database, and is the MIDP equivalent of the Persistent Store API. You can store and retrieve byte arrays using this method.

Data that your application stores by using the MIDP RMS is removed automatically when your application is removed from the device.

Runtime store

You can use this data storage option to store information and share that information between applications on the device by using the Runtime Store API. Data that your application stores in the runtime store is not retained after the device restarts.

Before you close your application, you should remove objects from the runtime store that your application no longer requires.

Choosing a data storage option

When you choose a data storage option to use in your application, you should keep in mind the following considerations:

Memory on mobile devices can be very limited, so you should consider not storing all of your data on the device. BlackBerry devices are frequently connected to wireless networks so that your application can access data when needed. In many cases, the best approach is to store data across device resets only when the data is frequently accessed.

The file system and MIDP RMS are standards-based approaches, and the persistent store and runtime store are specific to BlackBerry devices. If you want your application to run on other Java® ME compatible devices, you should consider a standards-based approach.

The file system is typically the most efficient storage location for large, read-only files such as videos or large graphics.

If you use the persistent store in your application, you should use the grouping mechanism that is provided in the net.rim.device.api.system.ObjectGroup class to commit groups of objects to memory more efficiently.

If you use the runtime store in your application, make sure that you remove objects that your application adds to the runtime store when they are no longer required. Failing to remove objects from the runtime store is a common cause of memory leaks in BlackBerry device applications.

The BlackBerry® Java® Virtual Machine includes a garbage collection tool, which runs periodically to remove unreferenced objects and weakly referenced objects from memory. To take advantage of this functionality in your application, you should release objects by setting their references to null after your application is done with them.

Code sample: Creating a file in internal storage

The following code sample demonstrates how to create a file in internal storage on the device.