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.

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

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

// override backlightStateChange() of the SystemListener2 interface
public void backlightStateChange(boolean on)
{
    if (screen != null)
    {
        if (on)
        {
            // set the Screen object of your application to listen for events from
            // your application
            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 application 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, visit the following resources:

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.

// 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

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.
  • For storing data other than large, read-only files, SQLite provides a scalable data storage option.
  • 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.

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, visit the following resources:

Next topic: Glossary

Was this information helpful? Send us your comments.