Headless applications

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

There are two main types of headless apps:

  • Short-running apps: These headless apps don't need to be running at all times, but instead they are typically triggered by some type of 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 period of time to monitor the device for certain activity. These apps might include instant messaging clients, fine-grained location trackers, or activity loggers.

Long-running headless apps will be first published in the BlackBerry World after the release of BlackBerry 10 OS version 10.2.1.

Both of these types of headless apps use triggers. A trigger is simply 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.

Enabling an app to run in the background is simple. Just create the two required parts of the app (UI part and headless part), modify the entry points of the app, request the user's permission, and use the invocation framework to enable the app to be triggered when a particular event occurs (for example, when some content is received). 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 then 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.

Application 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 important part to remember about CPU allocation is that 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 (namely, the _sys_headless_nostop permission), a long-running headless app can run for a longer period of 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 the notification service to do so. Note that 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 application 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 in such a way 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 NotificationDialog since BlackBerry 10 OS version 10.3.0.

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

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

LIBS += -lbbplatform

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

#include <bb/platform/Notification>
#include <bb/platform/NotificationDefaultApplicationSettings>

InvokeManager* _invokeManager;
Notification _notification;

Because we want to display instant preview notification when the headless app is triggered, we use signals and slots mechanism in the trigger samples. Modify the .cpp file as shown below:

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 application to the foreground when the user taps on the instant preview. This example uses com.example.UI as the UI target and will display action, MIME type, and data from the triggers in an instant preview notification.

void HeadlessApplication::onInvoked
(const bb::system::InvokeRequest& request)
{

    //Clear any existing notifications
    Notification::clearEffectsForAll();
    Notification::deleteAllFromInbox();

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

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


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

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

    //Displaying 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; it's completely up to you. 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. Here are a few approaches that you can consider to implement IPC in your headless app.

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.

To learn more about this approach, take a look at the XandOs and XandOsDroid sample app.

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.

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.

To learn more about this approach, check out the XandOs and XandOsDroid sample app.

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.

To learn more about this approach, see the HeadlessService and HeadlessServiceUI sample app.

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 that use Cascades APIs, see Debugging. To learn more about profiling Cascades 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 application > CPU > Stop.

When you're designing your headless app, you should consider how (and when) you want to close the headless part of the app. Remember that, by default, the headless part of a short-running app runs for 20 seconds when it's invoked. This is usually plenty of time 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's finished 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.

To explore different approaches to closing a headless app, see Sample applications.

Sample applications

To help you learn about the different types of headless apps and how you can create one effectively, you can take a look at a few sample apps. These sample apps are available in GitHub. For more sample apps, see the Sample apps page.

  • 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-09-30



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

comments powered by Disqus