Sorry about the red box, but we really need you to update your browser. Read this excellent article if you're wondering why we are no longer supporting this browser version. Go to Browse Happy for browser suggestions and how to update.

Efficient

For BlackBerry device users to enjoy using your application on a daily basis and recommend it to others, your application should be as efficient as possible. The features and charactaristics outlined in the other chapters - highly contextualized, always on, integrated and proactive - need to be implemented efficiently, or else your app can become less enjoyable to use.

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 apps.

What are the benefits of an efficient app?

  • Increase battery life. A longer battery life means that users can spend more time using your app and less time charging their devices or searching for apps to remove to improve performance (including yours!).
  • Improve response times. Efficient apps 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 app is transferring data unnecessarily. If your app transfers very little data while it's in use, your users are more likely to continue to use your app and recommend it to others.
  • Increase the "stickiness" of your app. A "sticky" app 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 app, you can improve your user's experience and help increase the stickiness of your app.

Approaches to efficient application design

The following approaches can help you make your app efficient.

Approach

Examples

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

You can use parameters and methods to check the device's power level, and other information. Depending on the status of the device, your app can respond accordingly. For example, your app might only download large files when connected to a Wi-Fi network, or stop downloading when available memory or the battery level is low.

Eliminate or defer unnecessary processing on the device.

If your app needs to perform complex calculations, you can do them when the device is idle. You can also push updates to your app on a schedule.

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

You can reduce the resources required to obtain a GPS location. Your app can perform full scans of the sky to locate satellites for a GPS fix only when necessary. In addition, when using assisted GPS mode, use it sparingly.

Use the Profiler tool to optimize your code.

The Profiler tool helps you find out what methods in your app take the most time to run, as well as how many objects it creates while running. By optimizing the most time-consuming methods, and reducing the amount of objects created, you can save device resources.

Responding to the status of the device

The Highly contextualized page describes how to consider the contexts (such as battery, connectivity, and device characteristics) that are associated with BlackBerry devices. When you design your app, the monitoring of certain contexts, or states, of the device can help your app be more efficient while also providing an exceptional user experience. Your app 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 app in response to state changes. For example, a Bookshelf app 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 app as a listener for different types of events. You might want your app 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 app 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.

Interface

Description

SystemListener2

You can use this listener to listen for system events, such as changes to the state of the backlight or changes to the state of the USB connection.

GlobalEventListener

You can use this listener to listen for global events, such as changes to the time zone or events that are associated with interprocess communication.

CoverageStatusListener

You can use this listener to listen for changes to wireless transports, such as HTTP over WAP or the BlackBerry Mobile Data System.

WLANConnectionListener

You can use this listener to listen for changes to Wi-Fi connectivity.

LowMemoryListener

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

If you choose to use listeners in your app, 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 app 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 app. A listener that you create yourself might be more focused or specialized for your app's functionality than a generic listener. For example, a listener that is designed for the Bookshelf app 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 app 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 app, to determine if there is sufficient battery power remaining to run your app 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 app to perform complex or time-consuming operations when the user is not using the device.

If your app must open a network connection, your app should check the network coverage that is available. If coverage is poor, your app 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 app 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 app is trying to use. For example, if the Disable GPS IT policy rule is applied to the device, your app 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 app for status changes to the wireless coverage. Your app can respond and stop transferring data or communicating with a server or web service.

public class MyApplication extends UiApplication implements CoverageStatusListener
{
    // class constructor
    public MyApplication()
    {
        // ...
    }

    public void coverageStatusChanged(int newCoverage)
    {
        // respond to the change in coverage
    }

    // ...
}

Code sample: Setting a listener when the backlight changes

The following code sample demonstrates how you can set a listener in your app when the backlight changes on the device. If the backlight is off, your app 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 app can resume listening for events.

// override backlightStateChange() of the SystemListener2 interface
public void backlightStateChange(boolean on)
{
    if (screen != null)
    {
        if (on)
        {
            // set the Screen object of your app to listen for events from
            // your app
            MyApplication.getInstance().setListener(screen);
        }
        else
        {
            MyApplication.getInstance().setListener(null);
        }
    }
}

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 app automatically or stop using GPS.

private boolean batteryLowNotCharging()
{
    int batteryStatus = DeviceInfo.getBatteryStatus();
    if ((batteryStatus & DeviceInfo.BSTAT_LOW) != 0)
    {
        if ((batteryStatus & DeviceInfo.BSTAT_CHARGING) == 0)
        {
            return true;
        }
    }
    return false;
}

Find out more

For more information about device status and network connections, see Networking and connectivity.

Eliminating unnecessary processing on the device

The Always on page describes how to keep your app 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 app by choosing when and how often to perform processing.

You can help make your app efficient by minimizing the amount of processing that you need to do in your app, and eliminating any processing that might not be necessary at a given time. For example, the Bookshelf app 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 app in the background if it makes sense to do so. Running your app in the background lets your app continue to process data and provide updates to the BlackBerry device user, even when the user is using other apps on the device. However, running in the background can consume valuable system resources and battery power. There are alternatives to running your app in the background:

  • You can push important information or updates to your app from an external source, such as a web server. Your app doesn't need to be running in the background to receive push notifications. When push data arrives on the device, if your app is registered as a push handler, your app processes the data automatically.
  • You can schedule processes to run periodically. Your app can perform resource-intensive operations at specific times so that your app doesn't run continuously.

When your app must perform tasks in the background, you can save battery power by making sure that your app 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 app 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 app is not displayed

If your app 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 app is running but not displayed, or if your app is not in use. You can use the following methods to determine if your app 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 app's screen is on top of the display stack and displayed to the user. You can override Screen.onObscured(), which is invoked when your app's screen is not displayed to the user or is obscured by another screen.
  • To determine if your app is in the foreground, you can invoke Application.isForeground(). If this method returns false, your app 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 app should not keep the backlight on unless the device is connected to a charger, or if screen visibility is critical to the app.
  • To determine how long the device has been idle, you can invoke Device.getIdleTime(). To prevent any potential UI lag or latency, your app should perform processor-intensive operations when the device is idle.

Find out more

For more information about pushing content to devices, see the Push Service SDK developer documentation.

Using location services effectively

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

You can help make your app efficient by making effective use of location services on the device, such as GPS and geolocation. For example, the Bookshelf app 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 done by GPS is 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 app that performs frequent full scans can drain the battery very quickly. To avoid this situation, your app should perform a full scan to obtain GPS fixes only as often as required to provide a good user experience. For example, your app might not need to maintain the user's exact position at all times, but instead can provide a good user experience if the app obtains a fix every ten minutes. If your app 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 app cannot obtain a GPS fix, you should consider carefully whether to retry the request. For example, if your app hasn't been able to obtain a fix for the last 30 minutes, it might be because the user is indoors, and your app shouldn't retry the request. Your app might also reduce the frequency of fix requests until a fix is successful.

Your app 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 app to use assisted GPS mode to obtain an initial fix before switching to autonomous GPS mode. If you want your app to obtain a fix using a particular GPS mode (for example, assisted GPS or autonomous GPS), your app 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 app 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 apps that don't always have access to GPS satellites (for example, apps 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.

// specify the geolocation mode
BlackBerryCriteria myBlackBerryCriteria = 
                   new BlackBerryCriteria(LocationInfo.GEOLOCATION_MODE);

// retrieve a location provider
BlackBerryLocationProvider myBlackBerryProvider = 
     (BlackBerryLocationProvider)LocationProvider.getInstance(myBlackBerryCriteria);

// request a single geolocation fix
BlackBerryLocation myBlackBerryLoc = myBlackBerryProvider.getLocation(timeout);

// retrieve the geolocation of the device
double lat = myBlackBerryLoc.getQualifiedCoordinates().getLatitude();
double lng = myBlackBerryLoc.getQualifiedCoordinates().getLongitude();
double lat = myBlackBerryLoc.getQualifiedCoordinates().getAltitude();

Find out more

For more information about GPS and location-based services, visit the following resources:

Using the Profiler tool

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. You can use the Profiler tool to identify what threads are running at any point in the execution of your app, how long methods take to run, how many objects your app creates, and so on.

You can use this tool to consider code-level efficiency when you're designing your app. You can make sure that the methods in your app 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 app creates a new object every time the app 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.

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 apps 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 app. You can also use profiler metrics to identify bottlenecks in your app's execution, and determine the best places to try to optimize your code.

You should try to optimize the methods in your app 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 app. 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 app is doing at any point during execution. Approximately every ten milliseconds, the Profiler tool queries your app, and your app 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 app, 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 app creates during execution. Object allocation and garbage collection are the primary reasons for UI lag or latency in an app, so if a method creates a large number of objects relative to other methods in your app, you should examine the objects to determine if they are all required. Your app 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 app 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 app 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 app 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, see the BlackBerry Java Plug-in for Eclipse Development Guide.

Storing data on the device

The Social and connected Social and connected page describes how to capture audio and video in your app by using the javax.microedition.media.Player class. In the code samples there, 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 app 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 app needs to store.

You can help make your app efficient by choosing the most appropriate storage location and storage option for your app's data. For example, the Bookshelf app 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 apps 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 app 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 app creates on a file system are not removed automatically when your app 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 app creates are not removed automatically when your app 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 app defines are removed automatically when your app 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 app stores by using the MIDP RMS is removed automatically when your app is removed from the device.

Runtime store

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

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

Choosing a data storage option

When you choose a data storage option to use in your app, 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 app 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 app 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.
  • For storing data other than large, read-only files, SQLite provides a scalable data storage option.
  • If you use the persistent store in your app, 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 app, make sure that you remove objects that your app 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 apps.
  • 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 app, you should release objects by setting their references to null after your app 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.

import net.rim.device.api.system.Application;
import javax.microedition.io.*;
import javax.microedition.io.file.*;
import java.io.IOException;

public class CreateFileApp extends Application
{
    public static void main(String[] args)
    {
        CreateFileApp app = new CreateFileApp();
        app.setAcceptEvents(false);
        try
        {
            FileConnection fc = (FileConnection)Connector.open("file:///store/home/user/newfile.txt");
            // If no exception is thrown, then the URI is valid, but the file may or
            // may not exist.
            if (!fc.exists())
            {
                // create the file if it doesn't exist
                fc.create();
            }
            fc.close();
        }
        catch (IOException ioe)
        {
            System.out.println(ioe.getMessage());
        {
    }
}

Code sample: Creating a SQLite database

The following code sample demonstrates how to create a SQLite database in the root folder of a media card.

import net.rim.device.api.system.Application;
import net.rim.device.api.database.*;
import net.rim.device.api.io.*;

public class CreateDatabase extends Application
{
    public static void main(String[] args)
    {
        CreateDatabase app = new CreateDatabase();
        try
        {
            URI strURI = URI.create("file:///SDCard/test.db");
            DatabaseFactory.create(strURI);
        }
        catch (Exception e)
        {
            System.out.println(e.getMessage());
        }
    }
}

Find out more

For more information about data storage, see the Data storage overview.