Headless apps

A headless app runs in the background on the BlackBerry 10 OS. Unlike other apps with a UI and an associated Active Frame, a headless app is not under the direct control of a user.

There are two types of headless apps:

  • Short-running apps: These headless apps don't need to be running at all times, but instead they are usually triggered by an event and run for a limited amount of time. These apps might include push message or port-directed SMS message receivers, downloaders (for podcasts or magazine subscriptions), or coarse-grained location trackers.
  • Long-running apps: These headless apps usually run for a long time to monitor the device for certain activity. These apps might include instant messaging clients, fine-grained location trackers, or activity loggers.

Both of these types of headless apps use triggers. A trigger is an event that prompts the headless app to start. This event might be a new SMS message, a change to the location of the device, or something else that you want your headless app to respond to. After a headless app is triggered, it can run as either a short-running app or a long-running app, depending on what tasks it needs to perform to handle the event. To learn more about triggers and which ones are available, see Triggers.

To enable an app to run in the background:

  1. Create the two required parts of the app (UI part and headless part).
  2. Modify the entry points of the app.
  3. Request the user's permission.
  4. Use the invocation framework to enable the app to be triggered when a particular event occurs (for example, when the app receives some content).

You create the headless part of the app by using a Cascades project in the Momentics IDE for BlackBerry. For the UI part, you can use Cascades or core APIs (or a combination of both). To learn how to create a headless app from start to finish, see Creating a headless app.

The following diagram provides an overview of the headless app process:

Diagram showing the headless app structure.

When an event (called the trigger source) occurs that you want your app to handle, the invocation framework handles the request and opens the headless part of your app. This part can notify the user that the event occurred by using notifications, and the user can choose to open the UI part of the app to respond to the event.

If you're using Cascades, you can learn more about notifications by reading Notifications. If you're using core APIs, see Notifications in the API reference.

App life cycle

Headless apps can be stopped and started again based on resource availability. If the BlackBerry device is running low on system resources, such as battery power level or RAM, the headless app receives a stop message and is given time to save its state and prepare for exit.

When the device resources are running low, processes are stopped depending on their importance to the user. This perceived importance of the processes is calculated using the ranking provided in the table below. The critical processes are considered the most important and the stop processes are considered the least important to the user.

Critical

Processes that must run at all times (for example, system processes)

Foreground

Processes that run in the foreground

Background

Processes that run in the background

Stop

Processes that are loaded to RAM without running

Resource management

By default, headless apps can occupy only 3 MB of memory. It's important to note that this limit applies only to the headless part of the app; the UI part can occupy more than 3 MB of memory, if necessary. This amount of memory should be sufficient for most headless apps because the headless part doesn't include UI elements, such as image assets.

The CPU that's allocated to a headless app is between 7% and 25% when running in the background. The headless part of your app receives a limited amount of CPU time compared to a normal app. The headless part might receive as little as 7%, or as much as 25%, of the CPU. You should keep this range in mind as you develop the headless part of your app, and make sure that intensive operations or long-running calculations aren't performed in the headless part, if possible.

Performance and battery life optimization

Headless apps should run for as little time as possible to minimize the consumption of battery power and optimize BlackBerry device performance. For this reason, headless apps are time-constrained. By default, a short-running headless app runs for 20 seconds each time it's invoked (triggered). However, with extra system permissions (that is, the _sys_headless_nostop permission), a long-running headless app can run for a longer time (even indefinitely) when it's triggered.

Long-running headless apps go through a rigorous testing and vetting process before they are published on the BlackBerry World storefront. As a best practice, long-running headless apps should use minimal memory and CPU cycles.

To learn more about the permissions that a headless app requires, see Specify the appropriate permissions.

Handling notifications

When a headless app needs to let the user know that a particular event has occurred, depending on the user settings, the app can send a notification to the user.

To provide a better user experience, headless apps can't bring their associated UIs to the foreground directly. Instead, headless apps use notifications (or the notification service, if you're using core APIs) to do so. The user can configure the notification settings for your app by using the Settings app on the device.

In addition to playing audible notifications and vibrating the device, a headless app can use the following types of notifications to bring something to the user's attention:

  • Notifications in the BlackBerry Hub for events that do not require immediate attention.
  • Instant previews for events that require immediate attention. The app should not be running in the foreground for it to be instantly previewed.

Screen shots showing the two types of notifications for headless apps.

Both of these notification types provide an option to the user to bring the UI part of the app to the foreground. You must implement the logic in your code so that, when it's triggered, your app sends a notification to the BlackBerry Hub or the Active Frame, or generates an instant preview. These types of notifications might require additional permissions.

Headless apps support dialog boxes in API level 10.3 or later of the BlackBerry 10 Native SDK. Only system dialog boxes, such as SystemDialog, are supported.

Enabling instant preview

You can enable instant previews for your headless apps by modifying the .pro, .hpp and .cpp files of the headless part of your app.

Modify the .pro file by linking the bb/platform library as shown below:

LIBS += -lbbplatform

Modify the .hpp file by adding the notification header files and creating an instance of the notification as shown below:

Not applicable

#include <bb/platform/Notification>
#include <bb/platform/NotificationDefaultApplicationSettings>
InvokeManager* _invokeManager;
Notification _notification;

Because you want to display an instant preview notification when the headless app is triggered, you can use the signals and slots mechanism. Modify the .cpp file as shown below:

Not applicable

connect(_invokeManager,
        SIGNAL(invoked(const bb::system::InvokeRequest&)),
        this,
        SLOT(onInvoked(const bb::system::InvokeRequest&)));
}

The code below shows how to enable instant preview in settings and add the targetType in invokeRequest to bring the UI of the app to the foreground when the user taps on the instant preview. This example uses com.example.UI as the UI target and displays the action, MIME type, and data from the triggers in an instant preview notification.

Not applicable

void HeadlessApplication::onInvoked
(const bb::system::InvokeRequest& request)
{
    // Clear any existing notifications
    Notification::clearEffectsForAll();
    Notification::deleteAllFromInbox();

    // Turn on previews in the Settings app
    bb::platform::NotificationDefaultApplicationSettings settings;
    settings.setPreview
    (bb::platform::NotificationPriorityPolicy::Allow);
    settings.apply();

    // Set the InvokeRequest for the UI
    InvokeRequest invokeReqNotification;
    invokeReqNotification.setTarget("com.example.UI");

    // Set the content of the body
    QString body;
    body = "action:- "+request.action()+" \n 
    "+"mime: "+ request.mimeType()+"\n"
    +" data :- "+ QString(request.data());

    // Set the body and the InvokeRequest of the notification
    _notification.setBody(QString::fromUtf8(body.toAscii()));
    _notification.setInvokeRequest(invokeReqNotification);

    // Display the instant preview
    _notification.notify();
}

You must grant your app permission to post notifications. In the bar-descriptor.xml file of the UI part of your headless app, navigate to the Application tab and select Post Notifications in the Permissions area.

Communicating between the UI and headless parts

In many headless apps that you develop, you may need to send information from the UI part of the app to the headless part, as well as from the headless part to the UI part. You could send user input from your app's UI to the headless part, or you might need to send event information from the headless part to display in the UI. You can use interprocess communication (IPC) techniques to send this information.

You can use any IPC technique you want to communicate between the parts of your headless app. You should determine the communication needs of your app and choose a solution (or a combination of solutions) that makes the most sense for you.

To learn more about the approaches that are described below, see the XandOs and XandOsDroid sample apps. You can also look at the HeadlessService and HeadlessServiceUI sample apps.

Invocation framework

You can use the invocation framework to invoke the headless part of your app from the UI part. For example, you might provide an option in your UI to start monitoring for incoming messages. When a user selects this option, the UI part of the app starts the headless part, which does the work of monitoring for new messages.

When you use this approach, you can't invoke the UI part from the headless part.

Local sockets

If the UI and the headless parts of your app need to communicate directly in real time, you can connect them using local sockets, such as the one that's implemented in QTcpSocket. You can also look at the Socket API, which is included as part of the core APIs and might provide the functionality that you need.

Sockets can be useful as an IPC mechanism in cases where the UI part and headless part need to set up a data stream for connection-oriented data transfer. For example, you might use this type of approach for a Voice over Internet Protocol (VOIP) app. You can use both TCP and UDP sockets, depending on how much error control your app requires.

QSettings and file monitoring

In many cases, the UI part of a headless app lets a user control the behavior of the headless part by using persistent settings. For example, you might provide a UI option that controls how often the headless part checks for updated data on a server, or another option that determines what action to take when a new message is received.

To implement this type of communication, you can use a QSettings object, or a file in the file system, that's shared between the two parts. Each part monitors the shared object or file and is notified when any changes occur.

Debugging and profiling

You can debug and profile your headless app just like any other apps that you develop. You can use the debugging and profiling tools that are available in the Momentics IDE for BlackBerry, as well as other techniques, such as qDebug() logging.

To learn more about debugging apps, see Testing and debugging. To learn more about profiling apps, see Profiling.

Closing a headless app

A user can close a headless app by navigating to Settings > App Manager > Device Monitor > Name of the app > CPU > Stop.

When you design your headless app, you should consider how (and when) you want to close the headless part of the app. By default, the headless part of a short-running app runs for 20 seconds when it's invoked. This time is usually enough to perform whatever operations are needed, so you may want to stop the headless part before the 20 seconds have elapsed. The UI part of your app can query to determine whether the headless part is running, and it can send a signal to indicate that the headless part should close. The headless part can also terminate itself when it finishes all of its work. Conversely, if a user starts the UI part but the headless part isn't running, you may want to start the headless part automatically.

For long-running headless apps, you should carefully consider in what circumstances (if any) the headless part should close. By anticipating situations where the headless part doesn't need to be running, you can proactively terminate it and save battery power and CPU.

Sample apps

To help you learn about the different types of headless apps and how you can create one effectively, you can look at a few sample apps.

  • PushCollector: A short-running headless app that shows you how to receive and process push messages
  • XandOs and XandOsDroid: A long-running headless app that shows you how to implement IPC using invocation and local sockets between the headless part and UI part of the app
  • HeadlessService and HeadlessServiceUI: A long-running headless app that shows you how to implement IPC using QSettings or file monitoring between the headless part and UI part of the app

If you want to learn how to create a simple headless app using a step-by-step approach, see Creating a headless app.

Last modified: 2014-12-11



Got questions about leaving a comment? Get answers from our Disqus FAQ.

comments powered by Disqus