This guide is a high level overview of the Urban Airship platform for Android and Amazon devices. We'll first cover the basic details of app setup before moving on to push notifications, client-side customization, and making use of our growing suite of integration and engagement tools.


Getting Started

There are a few important steps to get out of the way when integrating Urban Airship with your app for the first time. Follow these instructions carefully to ensure that you will have a smooth development experience.

SDK Installation

Example including FCM and ADM:

dependencies {

  // Urban Airship - FCM
  compile ''
  compile ''

  // Urban Airship - ADM
  compile ''

The Urban Airship SDK is split into modules which allow you to choose the push providers included in your application. You can install more than one provider if you have a single APK that uses both ADM and FCM. However FCM and GCM modules should not be included in the same APK. In the off chance that both are included, the SDK will log an error message and default to using the FCM module.

Artifact IdDescription
urbanairship-fcmFCM push provider support.
urbanairship-gcmGCM push provider support.
urbanairship-admADM push provider support.
urbanairship-coreThe core module. Automatically included in the other modules

All Urban Airship dependencies included in the build.gradle file should all specify the exact same version. The SDK will log an error if it detects urbanairship modules with mismatched version numbers at runtime.

Once you've chosen your modules, follow the setup steps below for each one.

FCM Setup


dependencies {

  // Urban Airship - FCM
  compile ''
  compile ''

Add the urbanairship-fcm module as a dependency in your application. Then follow FCM Android Setup and FCM Push Provider Setup to configure your application to use FCM.

If your application uses its own FirebaseMessagingService, FirebaseInstanceIDService, or some other third party push provider, you will also need to forward onTokenRefresh and onMessageReceived received calls to the Urban Airship SDK. For example:


public void onTokenRefresh() {
   // Notify Urban Airship that the token is refreshed.


public void onMessageReceived(RemoteMessage remoteMessage) {
   AirshipFirebaseMessagingService.processMessageSync(getContext(), remoteMessage);

ADM Setup


dependencies {

  // Urban Airship - ADM
  compile ''

Add the urbanairship-adm module as a dependency in your application. Then follow ADM Android Setup to configure Urban Airship to use ADM.

GCM Setup


dependencies {

  // Urban Airship - ADM
  compile ''

Add the urbanairship-gcm module as a dependency in your application. Then follow FCM Android Setup to configure Urban Airship to use GCM/FCM.

Create Airship Config Options


developmentAppKey = Your Development App Key
developmentAppSecret = Your Development App Secret

productionAppKey = Your Production App Key
productionAppSecret = Your Production Secret

# Toggles between the development and production app credentials
# Before submitting your application to an app store set to true
inProduction = false

# LogLevel is "VERBOSE", "DEBUG", "INFO", "WARN", "ERROR" or "ASSERT"
developmentLogLevel = DEBUG
productionLogLevel = ERROR

# FCM/GCM Sender ID
fcmSenderId = Your Google API Project Number

# Notification customization
notificationIcon = ic_notification
notificationAccentColor = #ff0000

# Optional, set the default notification channel
notificationChannel = customChannel

Airship config options are a convenient way to pass custom settings to your app without needing to edit the source code. By default the Urban Airship SDK loads these settings from the file located in your application's assets directory. Use this file, among other things, to set the backend credentials for your app, and to toggle between development and production builds.


Basic Autopilot integration:

<meta-data android:name="com.urbanairship.autopilot"

The Urban Airship SDK must be initialized before any receiver, service, or activity is created. This is achieved by calling takeOff manually in the application's onCreate method or by using Autopilot .

Autopilot will automatically call takeOff when the application initializes without the need to override any Application methods. The class can be used directly to use configuration loaded from the file. It can also be extended to customize the airship config and to receive a callback when the Airship instance is ready.

Customizing Autopilot

Extending Autopilot example:

public class SampleAutopilot extends AutoPilot {

  public void onAirshipReady(@NonNull UAirship airship) {

      // Android O
      if (Build.VERSION.SDK_INT >= 26) {
          Context context = UAirship.getApplicationContext();
          NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

          NotificationChannel channel = new NotificationChannel("customChannel",


  public AirshipConfigOptions createAirshipConfigOptions(@NonNull Context context) {
      AirshipConfigOptions options = new AirshipConfigOptions.Builder()
          .setDevelopmentAppKey("Your Development App Key")
          .setDevelopmentAppSecret("Your Development App Secret")
          .setProductionAppKey("Your Production App Key")
          .setProductionAppSecret("Your Production App Secret")
          .setFcmSenderId("Your Google API Project Number") // FCM/GCM sender ID
          .setNotificationAccentColor(ContextCompat(getContext(), R.color.accent))

      return options;

Register the extended Autopilot class:

<meta-data android:name="com.urbanairship.autopilot"

To use Autopilot, add metadata within the application entry to the AndroidManifest.xml. The name of the meta-data com.urbanairship.autopilot and the value should be the fully qualified class name.

Send Your First Push Notification

Enable user notifications:


At this point in the guide, if you followed all the steps above you should be ready to send a test push notification to verify everything is set up properly. Before sending a push, make sure you have enabled user notifications.

Follow Send Your First Notification or our API reference for details on sending the first notification.

Android Things

Urban Airship is compatible with devices running Android Things. Urban Airship treats devices running Android Things the same as standard Android devices throughout our stack. Push messages, in-app messaging, Message Center, and analytics are all supported.

Push Notifications

Disable user notifications:


Android Things does not support displaying notifications, so you will want to make sure setUserNotificationsEnabled is disabled. See Listening for Push Events to learn how to receive a callback when a new push message is received.

Urban Airship Channel IDs

String channelId = UAirship.shared().getPushManager().getChannelId();"My Application Channel ID: " + channelId);

The Channel ID is a unique identifier that ties together an application/device pair on Android and Amazon devices. The Channel ID is used to target pushes to specific devices using the Urban Airship API. Once a Channel ID is created, it will persist the application until it is either reinstalled, or its internal data is cleared.

Don't worry if this value initially comes back as null on your app's first run (or after clearing the application data), as the Channel ID will be created and persisted during registration. To receive an event when the Channel ID is created, see Listening for Push Events.

Channel Capture Tool

The Channel ID is valuable for troubleshooting individual device issues in production apps. Android SDKs since 6.1.0 include a Channel Capture tool that can be used to expose the Channel ID to the user, who can then send it to support. App developers are asked to enable the channel capture tool or to provide another mechanism to get the user's channelID.

The Channel Capture tool can be enabled or disabled using the channelCaptureEnabled flag in your app's

  • The Channel Capture tool is enabled by default. This is the recommended setting.
  • If the app disables the Channel Capture tool, it should provide some other mechanism to expose the user's Channel ID.

When channel capture is enabled and the app becomes active, the Channel Capture tool only operates if it is active. There are two situations where it is active:

Activating the Channel Capture tool:

final long duration = 180;
  • Notifications are disabled in the app's system settings, or
  • The Channel Capture tool has been activated for a specific duration, either by

If the Channel Capture tool is active, it looks for a special token placed by the user on the device's clipboard. Urban Airship Support can help developers generate this token. If and only if the special token matches an SDK-generated token, a dialog is displayed that allows the user to copy their Channel ID. The Channel ID can then be sent from the user to support to help troubleshoot the issue.

Listening for Airship Events

Sample AirshipReceiver:

public class SampleAirshipReceiver extends AirshipReceiver {

    private static final String TAG = "SampleAirshipReceiver";

    protected void onChannelCreated(@NonNull Context context, @NonNull String channelId) {
        Log.i(TAG, "Channel created. Channel Id:" + channelId + ".");

    protected void onChannelUpdated(@NonNull Context context, @NonNull String channelId) {
        Log.i(TAG, "Channel updated. Channel Id:" + channelId + ".");

    protected void onChannelRegistrationFailed(Context context) {
        Log.i(TAG, "Channel registration failed.");

    protected void onPushReceived(@NonNull Context context, @NonNull PushMessage message, boolean notificationPosted) {
        Log.i(TAG, "Received push message. Alert: " + message.getAlert() + ". posted notification: " + notificationPosted);

    protected void onNotificationPosted(@NonNull Context context, @NonNull NotificationInfo notificationInfo) {
        Log.i(TAG, "Notification posted. Alert: " + notificationInfo.getMessage().getAlert() + ". NotificationId: " + notificationInfo.getNotificationId());

    protected boolean onNotificationOpened(@NonNull Context context, @NonNull NotificationInfo notificationInfo) {
        Log.i(TAG, "Notification opened. Alert: " + notificationInfo.getMessage().getAlert() + ". NotificationId: " + notificationInfo.getNotificationId());

        // Return false here to allow Urban Airship to auto launch the launcher activity
        return false;

    protected boolean onNotificationOpened(@NonNull Context context, @NonNull NotificationInfo notificationInfo, @NonNull ActionButtonInfo actionButtonInfo) {
        Log.i(TAG, "Notification action button opened. Button ID: " + actionButtonInfo.getButtonId() + ". NotificationId: " + notificationInfo.getNotificationId());

        // Return false here to allow Urban Airship to auto launch the launcher
        // activity for foreground notification action buttons
        return false;

    protected void onNotificationDismissed(@NonNull Context context, @NonNull NotificationInfo notificationInfo) {
        Log.i(TAG, "Notification dismissed. Alert: " + notificationInfo.getMessage().getAlert() + ". Notification ID: " + notificationInfo.getNotificationId());

Register the receiver in the AndroidManifest.xml:

<receiver android:name=".SampleAirshipReceiver"

        <action android:name="com.urbanairship.push.CHANNEL_UPDATED" />
        <action android:name="com.urbanairship.push.OPENED" />
        <action android:name="com.urbanairship.push.RECEIVED" />
        <action android:name="com.urbanairship.push.DISMISSED" />
        <category android:name="${applicationId}" />

To listen for push and registration events generated by the Urban Airship SDK, extend the AirshipReceiver .

AirshipReceiver is a base class that handles parsing the raw intents for the application and provides convenient listener style callbacks. Extend the class and register the receiver in the AndroidManifest.xml.

Push Notifications

Urban Airship's SDK provides a simple interface for managing push notifications within your Android application.

Enabling User Notifications

Enable user notifications:


The Urban Airship SDK makes a distinction between "user notifications", which can be seen by the user, and other forms of push that allow you to send data to your app silently.

Enabling or disabling user notifications is a preference often best left up to the user, so by default, user notifications are disabled. However they are easily enabled with a single call to the PushManager instance.

Notification Channels

Creating custom notification channels:

NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

NotificationChannel channel = new NotificationChannel("customChannel",


// Either set the default channel in the airship config or directly
// on the notification factory:

Quiet time, sound, and vibration settings have been superseded by notification channels on Android O and newer devices.

Starting with Android O, each notification must assign a valid notification channel or the notification will not display. The SDK will automatically assign a default channel with the name "Notifications". The default channel can be overridden either in AirshipConfigOptions or by setting it directly on the NotificationFactory . The notification channel can also be set per message by specifying the channel's ID in the Push API.

Quiet Time

// Set the quiet time from 7:30pm - 7:30am
SimpleDateFormat formatter = new SimpleDateFormat("hh:mm", Locale.US);
Date startDate = formatter.parse("19:30");
Date endDate = formatter.parse("07:30");


// Enable quiet time

Quiet time has been superseded by notification channels on Android O and newer devices. However it is still useful for older devices.

Quiet time disables push notification sounds and prevents the phone from vibrating during the set time frame.

Clearing Notifications

Clear all Notifications


Notifications can be cleared manually by using standard Android APIs on the NotificationManager or NotificationManagerCompat classes.

Customizing Push Notifications


The DefaultNotificationFactory is the recommended factory as it provides full support for all of the Android push features.

All incoming push notifications are built using a class that extends the NotificationFactory .

The Urban Airship SDK uses the DefaultNotificationFactory . With this factory, the standard Android Notification layout will use the application's title and icon. A default big text style will be applied for all notifications.

Common customizations:

NotificationFactory factory = UAirship.shared().getPushManager().getNotificationFactory();

// Customize the factory
factory.setColor(ContextCompat.getColor(context, R.color.notification_color));

Accent color, notification icons, default sound, and default title can all be modified by calling the appropriate setter on any of the NotificationFactory instances.

Custom Notification Factories

Custom Factory Example:

public class CustomNotificationFactory extends NotificationFactory {

    public CustomNotificationFactory(Context context) {

    public Notification createNotification(PushMessage message, int notificationId) {
        // do not display a notification if there is not an alert
        if (UAStringUtil.isEmpty(message.getAlert())) {
            return null;

        // Build the notification
        NotificationCompat.Builder builder = new NotificationCompat.Builder(getContext())
                .setContentTitle("Notification title")

        // Notification action buttons
        builder.extend(new ActionsNotificationExtender(getContext(), message, notificationId));


    public int getNextId(PushMessage pushMessage) {
        return NotificationIdGenerator.nextID();

    * Checks if the push message requires a long running task. If {@code true}, the push message
    * will be scheduled to process at a later time when the app has more background time. If {@code false},
    * the app has approximately 10 seconds total for {@link #createNotification(PushMessage, int)}
    * and {@link #getNextId(PushMessage)}.
    * <p>
    * Apps that return {@code false} are highly encouraged to add {@code RECEIVE_BOOT_COMPLETED} so
    * the push message will persist between device reboots.
    * @param message The push message.
    * @return {@code true} to require long running task, otherwise {@code false}.
   public boolean requiresLongRunningTask(PushMessage message) {
       return false;


Register the factory once UAirship is ready:

public void onAirshipReady(UAirship airship) {

    // Create a customized default notification factory
    CustomDefaultNotificationFactory notificationFactory;
    notificationFactory = new CustomDefaultNotificationFactory(UAirship.getApplicationContext());

    // Set the factory on the PushManager

Custom notification factories are supported, but may cause some Android Push features to no longer work. Only features that the custom factory implements will be available.

Available Notification Factories

The Urban Airship SDK contains several notification factories to help simplify creating custom notifications. Any one of them can be extended.

Base factory class. Builds notifications without any default styles.
The default SDK factory. Builds notifications with a default big text style.
Builds custom layout notifications.

Available Notification Extenders

The SDK also provides several notification builder extenders to help support Android Push features.

Supports Android Notification Action Button API features.
Supports Public Notification API features.
Supports Android style API features.
Supports Android Wear API features.

Addressing Devices

To help target specific devices or users for a notification, we have Tags, Named Users and Tag Groups.


Modifying tags:


Tags allow you to attribute arbitrary metadata to a specific device. Common examples include favorites such as sports teams or news story categories.

Named Users

Setting the named user:

// Associate the channel to a Named User ID.

Associating the channel with a Named User ID will implicitly disassociate the channel from the previously associated Named User ID, if an association existed.

Named Users allow you to associate multiple devices to a single user or profile that may be associated with more than one device, e.g., an end-user's Android phone and tablet. A device can have only one Named User, and a single Named User should not be associated with more than 50 devices. Named Users provide the ability to directly set tags on them (see Tag Groups).

By default, Named Users cannot be associated from the device. In this case if the devices attempts a Named User association, the association will fail and the SDK will log an error. In order to change this setting, see the Settings documentation.

Tag Groups


If setting channel tags is enabled during registration, the predefined device Tag Group cannot be modified from the device and will log an error message. Disable channel tags by setting setChannelTagRegistrationEnabled to false on the PushManager instance if you want to modify this "default" Tag Group.

Channel Tag Group Example:

                .addTag("loyalty", "bronze-member")
                .removeTag("loyalty", "bronze-member")
                .setTag("games", "bingo")

Named User Tag Group Example:

                .addTag("loyalty", "bronze-member")
                .removeTag("loyalty", "bronze-member")
                .setTag("games", "bingo")

Tag groups are configurable namespaces for organizing tags for the channel and Named User. Please view the Tag Groups documentation for more details. The Create and push to a tag group guides you through creating and using Tag Groups.

By default, Tag Groups cannot be modified from the device. In this case if a device attempts to modify Tag Groups, the modification will fail and the SDK will log an error. In order to change this setting, see the Settings documentation.

Custom Identifiers

Setting custom identifiers:

           .addIdentifier("key", "value")

Automatically track the Android Advertising ID:


In addition to Named Users, tags and Tag Groups, you can assign up to 20 custom identifiers to users. Identifiers that define additional ways of looking at a user— for example, Android Advertising ID, Google Analytics CID, or any other identifier you deem significant -- can be added to your users.

Custom identifiers will be visible in the Connect data stream. We recommend adding any IDs that you may want to be visible in Connect, even if Connect does not yet support the relevant integration. Unlike the other identifiers (e.g., tags), you cannot use custom identifiers to target your users.

Interactive Notifications

Urban Airship provides a set of standard Interactive Notification types (See: Built-In Interactive Notification Types). It is the type that determines which buttons and corresponding labels will be available when you send a push. See the next section for where to specify that in the push payload. You control what happens when you send the push separately, by tying each button ID to a specific action.

Custom Interactive Notification Types (Notification Action Button Groups)


// Define actions for the group
NotificationActionButton hiButtonAction = new NotificationActionButton.Builder("hi")

NotificationActionButton byeButtonAction = new NotificationActionButton.Builder("bye")

// Define the group
NotificationActionButtonGroup buttonGroup = new NotificationActionButtonGroup.Builder()

// Add the custom group
airship.getPushManager().addNotificationActionButtonGroup("custom group", buttonGroup);

Urban Airship reserves category IDs prefixed with ua_. Any custom groups with that prefix will be dropped.

If you want to define a custom Interactive Notification type, you must register a new notification action button group.

Custom NotificationActionButtonGroups are supported by registering the groups with the PushManager right after UAirship.takeOff using the PushManager.addNotificationActionButtonGroup method.

In-App Messaging

In-App Messages are messages that appear inside of your app, regardless of the opt-in/opt-out status of a user notifications. For more information, please read the Android In-App Messaging Guide,

Message Center

Displaying the Message Center

Displaying the Message Center:


Message Center Display intent filter:

    <action android:name="com.urbanairship.VIEW_RICH_PUSH_INBOX" />
    <category android:name="android.intent.category.DEFAULT" />

> Displaying a specific message:

<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">UAirship<span style="color:#f92672">.</span><span style="color:#a6e22e">shared</span><span style="color:#f92672">().</span><span style="color:#a6e22e">getInbox</span><span style="color:#f92672">().</span><span style="color:#a6e22e">startMessageActivity</span><span style="color:#f92672">(</span>messageId<span style="color:#f92672">);</span></code></pre></div>

<!-- Route message displays through a Message Center -->
    <action android:name="com.urbanairship.VIEW_RICH_PUSH_INBOX" />
    <data android:scheme="message"/>
    <category android:name="android.intent.category.DEFAULT" />

Message display intent filter:

    <action android:name="com.urbanairship.VIEW_RICH_PUSH_MESSAGE" />
    <data android:scheme="message"/>
    <category android:name="android.intent.category.DEFAULT" />

Parsing message from intents:

RichPushMessage message = null;

if (RichPushInbox.VIEW_INBOX_INTENT_ACTION.equals(intent.getAction()) {
    if (getIntent().getData().getScheme().equalsIgnoreCase(RichPushInbox.MESSAGE_DATA_SCHEME)) {
        String messageId = getIntent().getData().getSchemeSpecificPart();
        message = UAirship.shared().getInbox().getMessage(messageId);

The Message Center can be displayed any time by calling RichPushInbox.startInboxActivity() . A specific message can be displayed by calling RichPushInbox.startMessageActivity :

RichPushInbox.startInboxActivity() will either launch the MessageCenterActivity or it can be customized by the application by adding the appropriate intent filters to an activity in the AndroidManifest.xml.

Styling the Message Center


<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
   <!-- Set the custom Message Center style -->
   <item name="messageCenterStyle">@style/AppTheme.MessageCenter</item>

 <style name="AppTheme.MessageCenter" parent="MessageCenter">
     <item name="messageCenterDividerColor">#44000000</item>
     <item name="messageCenterItemIconEnabled">true</item>
     <item name="messageCenterItemTitleTextAppearance">@style/AppTheme.MessageCenter.TitleTextAppearance</item>
     <item name="messageCenterItemDateTextAppearance">@style/AppTheme.MessageCenter.DateTextAppearance</item>

 <!-- Custom message title text style -->
 <style name="AppTheme.MessageCenter.TitleTextAppearance" parent="MessageCenter.Item.Title.TextAppearance">
     <item name="android:textSize">30sp</item>
     <item name="android:textStyle">italic</item>
     <item name="android:textColor">@android:color/black</item>
     <item name="urbanAirshipFontPath">"fonts/CustomFont.ttf"</item>

 <!-- Custom message date text style -->
 <style name="AppTheme.MessageCenter.DateTextAppearance" parent="MessageCenter.Item.Date.TextAppearance">
     <item name="android:textSize">16sp</item>
     <item name="urbanAirshipFontPath">"fonts/CustomFont.ttf"</item>

The Message Center can be styled by providing a custom style in the application's theme with the attribute messageCenterStyle. The Message Center can be customized with the following attributes:

A drawable for the message item's background
Text appearance style for the message's title
Text appearance style for the message's date
Flag to enable message list icons instead of a checkbox
The default placeholder when using message list icons
Text appearance style for the no message selected text when displaying the Message Center in a tablet view
String to use for the "no message selected" text when displaying the Message Center in a tablet view.
Text appearance style for the empty message list text
String to use for the empty message list text
The message list divider color
Text appearance attribute that defines a path to custom font in the assets directory

Message Center Filtering

Filtering messages:

RichPushInbox.Predicate pred = new RichPushInbox.Predicate() {
    public boolean apply(RichPushMessage message) {
        return message.getTitle().contains("Cool");


Sometimes it can be useful to filter the contents of the message center according to some predetermined pattern. To facilitate this, use the shared MessageCenter instance to set a predicate. Once set, only messages that match the predicate will be displayed.

Embedding the Message Center

Embedding the MessageCenterFragment in a layout xml:

    android:layout_height="match_parent" />

Embedding the MessageCenterFragment using a fragment transaction:

MessageCenterFragment fragment = new MessageCenterFragment();
                                   .replace(, fragment, "message_center")

The Message Center can be embedded in any FragmentActivity using MessageCenterFragment .


Urban Airship Actions provides a convenient way to automatically perform tasks by name in response to push notifications, Message Center interactions and JavaScript.

An action is an abstraction over a unary function, which takes an argument and performs a defined task, producing an optional result. Actions may restrict or vary the work they perform depending on the arguments they receive, which may include type introspection and runtime context.

The Urban Airship SDK comes with pre-made actions for common tasks such as setting/modifying tags, showing a landing page, scheduling or canceling action schedules, and deep linking. Actions can also be extended to enable custom application behaviors and engagement experiences.

Actions are sent with a push by supplying a JSON payload as a push extra with the key com.urbanairship.actions. The JSON payload is a map of the action names to action values. The values can be any valid JSON value.

Action Situations

Actions are triggered with additional context in the form of a Situation, which corresponds to the way the action was triggered. The different situations allow actions to determine whether they should run, or potentially perform different behaviors depending on this context.

Action is invoked manually.
Action is triggered when a push is received.
Action is triggered when a notification is opened.
Action is triggered from a web view.
Action is triggered from a foreground notification action button.
Action is triggered from a background notification action button.
Action is triggered from automation.

Action Registry

Registering an action:

Action customAction = new CustomAction();
         .registerAction(customAction, "my_action_name");

Looking up an entry:

ActionRegistry.Entry entry = UAirship.shared()

Setting a predicate:

// Predicate that will reject PUSH_RECEIVED causing the action to never run during that situation.
Predicate<ActionArguments> rejectPushReceivedPredicate = new Predicate<ActionArguments>() {
    public boolean apply(ActionArguments arguments) {
        return !(Situation.PUSH_RECEIVED.equals(arguments.getSituation()));


The action registry is the central place to register actions by name. Each entry in the registry contains an action, the names that the action is registered under, a predicate that allows filtering when an action can run, and allows specifying alternative actions for different situations.

Triggering Actions


// Running an action directly through the ActionRunRequest

// Running an action by registered name

// An optional callback when finished
                .run(new ActionCompletionCallback() {
                    public void onFinish(ActionArguments arguments, ActionResult result) {
              "Action finished!  Result: " + result);

// Block until the action finishes
ActionResult result = ActionRunRequest.createRequest("my_action_name")

Actions can be triggered programmatically through an ActionRunRequest , by defining actions in a push notification, from JavaScript using a Custom HTML Template, or from an automation schedule.

The ActionRunRequest class provides a fluent API for running actions. The action run request takes in a value, situation, and metadata and constructs the ActionArguments and passes it to the action to run.

The ActionArguments value can only contain an ActionValue instance. ActionValue is a class that limits the type of values to those that can be JSON serializable and contain getter methods that automatically do type checking to parse value back into its original form. Each action is run on its own thread when triggered asynchronously. Synchronous runs will block and should never be called on the UI thread.

Available Actions

The landing page action allows showing a rich content page in an overlay.
The open external URL action allows launching any URL. The action will construct an intent with a given URI and try to start an activity with it for viewing.
The deep link action works exactly as the Open External URL Action. It constructs an intent with a given URI and tries to launch an activity. The deep linking strategy assumes the application is set up to handle URIs. See Deep Linking for Android for more details on providing deep linking.
The share action constructs an intent to share the text to the application. The Android chooser activity will be started to pick the application used to share the text.
The add tags action allows adding one or more tags to the device. Note: this action is a no-op if channelTagRegistrationEnabled is set to false on PushManager .
The remove tags action allows removing one or more tags from the device.
The custom event action creates and adds a custom event. See Custom Events documentation for more details on Custom Events.
The clipboard action copies text to the system clipboard.
The open rich push inbox action will try to start an activity to view either the Message Center Inbox or Message if a message ID is supplied as the argument's value and the message is present in the inbox.
The overlay rich push action will display a Message Center Message in the landing page activity.
The wallet action allows opening Google Pay deep links.
The schedule action schedules an automation action.
The cancel schedules action cancels automation actions.
The fetch device info action gets an updated snapshot of the device's information from the JavaScript bridge.
The enable feature action enables an Urban Airship feature, such as location, background location, or user notifications.

Custom Actions

Custom Action:

public class CustomAction extends Action {

    public boolean acceptsArguments(ActionArguments arguments) {
        if (!super.acceptsArguments(arguments)) {
            return false;

        // Do any argument inspections. The action will stop
        // execution if this method returns false.

        return true;

    public ActionResult perform(ActionArguments arguments) {"Action is performing!");

        return ActionResult.newEmptyResult();

Register the action after takeOff:

public void onAirshipReady(UAirship airship) {
             .registerAction(new CustomAction(), "my_custom_action");

The action framework supports any custom actions. Create an action by extending the base action class, then register the action to the registry after UAirship.takeOff .

The action can then be triggered the same way as the built-in actions.


Actions that are long-lived should request a wake lock before performing. This is especially important for actions that are performing in Situation.PUSH_RECEIVED, when a push is delivered when the device is not active.

On-Device Automation

On-device automation allows the Urban Airship SDK to execute actions when certain conditions are met upon the creation of an analytics event. These conditions are defined as triggers and range from app foreground to screen events. Actions can be scheduled either through an action or using the APIs exposed by the SDK.

Using the Automation Actions

Example schedule payload that will display a landing page after a user has either visited a given page ten times or, as reported through a custom event, purchased items beyond a threshold of $30.

   "schedule_actions" :{
      "limit": 1,
      "start": "2015-04-01T12:00:00",
      "end": "2017-05-01T12:00:00",
      "group": "campaign 1",
      "triggers": [
            "type": "screen",
            "goal": 10,
            "predicate": {
               "value": {
                  "equals": "purchase_page"
            "type": "custom_event_count",
            "goal": 1.0,
            "predicate": {
               "and" : [
                  "key": "event_name",
                  "value": {
                     "equals": "purchase"
                  "key": "price",
                  "scope": ["properties"],
                  "value": {
                     "at_least": "30.0"

The "schedule_actions" action enables scheduling through the Push API as an "app defined" action, through the Urban Airship JavaScript bridge, or directly in the SDK by manually running the action. There are several components to this schedule payload.

Schedule Payload

Optional, group identifier. Useful for canceling and retrieving schedules for a specific campaign.
Optional, start time as an ISO 8601 timestamp. The time before the schedule starts listening for events.
Optional, end time as ISO 8601 timestamp. Once the schedule end time is reached, it will automatically be canceled.
Required, an array of triggers. Triggers cause the actions payload to execute.
Optional, a payload of time and/or app conditions that must be met before the actions are able to be executed. The delay occurs after one of the triggers hits its goals.
Optional, integer defaulting to 1. Number of times to trigger the actions payload before canceling the schedule.
Required, map of actions payloads. Run when one or more of the triggers meets its goal.

Trigger Payload

Required, the event type. Must be one of the valid types below. Each trigger type defines how the goal is incremented and the predicate argument.
Required, the trigger's goal. When the trigger's goal is met, it will trigger the schedule's actions to be executed.
Optional, predicate to filter out events.

Trigger Types

Custom event's value will be applied to the trigger's goal. Predicate is applied to the event.
Custom events will be counted towards the trigger's goal. Predicate is applied to the event.
App init counts will be counted towards the trigger's goal. The predicate is ignored.
App foreground counts will be counted towards the trigger's goal. Predicate is ignored.
App background counts will be counted towards the trigger's goal. The predicate is ignored.
Region enter events will be counted towards the trigger's goal. Predicate is applied to the event.
Region exit events will be counted towards the trigger's goal. Predicate is applied to the event.
Screen tracking. Predicate is applied against the screen's name.

Trigger Predicates

Predicate syntax:

<predicate>        := <json_matcher> | <not> | <and> | <or>
<not>              := { "not": { <predicate> } }
<and>              := { "and": [<predicate>, <predicate>, …] }
<or>               := { "or": [<predicate>, <predicate>, …] }
<json_matcher>     := { <selector>, "value": { <value_matcher> }} | { "value": {<value_matcher>}}
<selector>         := <scope>, "key": string | "key": string | <scope>
<scope>            := "scope": string | "scope": [string, string, …]
<value_matcher>    := <numeric_matcher> | <string_matcher> | <presence_matcher>
<numeric_matcher>  := "equals": number | "at_least": number | "at_most": number | "at_least": number, "at_most": number
<string_matcher>   := "equals": string
<presence_matcher> := "is_present": boolean

The predicate is the core logic within the trigger, presenting a set of structured conditions that are applied to the trigger event. It follows the same patterns as in Custom Event Selectors and may be a value matcher or logical expression.

Delay Payload

Example delay payload:

"delay": {

  // Minimum time in seconds that is needed to pass before running the actions
  "seconds": 10.5,

  // Specifies the ID of a region that the device must currently be in before
  // the schedule's actions are able to be executed.
  "region_id": "region id",

  // Specifies the name of an app screen that the user must currently be
  // viewing before the schedule's actions are able to be executed.
  "screen": "screen name",

  // Specifies the app state that is required before the schedule's actions
  // are able to execute. Either foreground or background.
  "app_state": "foreground",

  // These triggers will cancel the pending execution of the actions
  "cancellation_triggers": [ // triggers ],
Optional, minimum time in seconds that is needed to pass before running the actions.
Optional, specifies the ID of a region that the device must currently be in before the schedule's actions are able to be executed.
Optional, specifies the name of an app screen that the user must currently be viewing before the schedule's actions are able to be executed.
Optional, specifies the app state that is required before the schedule's actions are able to execute. Either "foreground" or "background".
Optional, triggers that will cancel the pending execution of the actions.

Cancelling Actions

Example cancel action payload:

// Cancel all scheduled actions
"cancel_scheduled_actions": "all"

// Cancel specific groups and/or ids
"cancel_scheduled_actions": {
   "ids": ["id 1", "id 2"],
   "groups": ["campaign 1", "campaign 2"]

Just like scheduling actions, canceling scheduled actions can be done with the "cancel_scheduled_actions" action.

Optional. Value for canceling all schedules.
Optional. Either a single group or an array of groups
Optional. Either a single ID or an array of IDs

Using the Automation API

Scheduling actions example:

Trigger customEventTrigger = Triggers.newCustomEventTriggerBuilder()

Trigger foregroundEventTrigger = Triggers.newForegroundTriggerBuilder()

ActionScheduleInfo actionSchedule = ActionScheduleInfo.newBuilder()
                                                      .addAction("sample_action", JsonValue.wrap("sample_action_value"))
                                                      .setEnd(System.currentTimeMillis() + TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS))

// Schedule the schedule info

It should be noted that the automation module cannot be accessed off of the main process. If any method is called, the method will no-op and execute the callback, if provided.

The API provided in Automation allows for synchronous and asynchronous access to the automation storage. To schedule an action schedule, first create an ActionScheduleInfo object.

When an ActionScheduleInfo instance is scheduled, the module will return an ActionSchedule instance with a unique ID generated for the schedule. When scheduling asynchronously, a callback may be provided to handle this response. If present, the callback will be posted to the calling thread's looper. The main thread's looper will otherwise be used.

Retrieving Scheduled Actions

Retrieving a specific schedule:

PendingResult<ActionSchedule> pendingResult = UAirship.shared().getAutomation().getSchedule("id");

Retrieving schedules from a group ID:

PendingResult<ActionSchedule> pendingResult = UAirship.shared().getAutomation().getSchedules("group");

The API provides methods for retrieving a single schedule, group of schedules, or all schedules. If retrieving asynchronously, a callback may be provided.

Cancelling Scheduled Actions


Lastly, a series of methods are provided for canceling a single schedule, a group or list of schedules, or all schedules.

Analytics and Reporting

This document is a quick guide to integrating Reports support with your Android application using the Urban Airship client library. We will briefly cover the event upload model the client library implements.

Analytics Events and Uploading

Our client library stores events in a local database and uploads them periodically in a background thread. We've taken great care to make sure that the database won't grow beyond a small fixed size, so extended periods of lost connectivity are nothing to worry about. The event upload thread is woken up when new events are triggered and goes to sleep when there are no more events to process, so the impact on battery life is negligible.

Custom Events

Recording custom events:

CustomEvent.Builder builder = new CustomEvent.Builder("event_name")
                .addProperty("my custom property", "some custom value");

// Set custom event properties on the builder
builder.addProperty("bool_property", true);
builder.addProperty("string_property", "string_property_value");
builder.addProperty("int_property", 11);
builder.addProperty("double_property", 11.0d);
builder.addProperty("long_property", 11L);

ArrayList<String> collection = new ArrayList<String>();
builder.addProperty("collection_property", collection);

// Record the event

Custom events let you track user activities and key conversions in your application, and tie them back to corresponding push messaging campaigns. Custom events require analytics to be enabled. If disabled, any event that is added to analytics will be ignored. For a more detailed explanation on custom events and possible use cases, see the Custom Events topic guide.

Convenient templates are provided to create custom events for common account, media or retail related events. For more details see the Custom Event Templates topic guide.

Screen Tracking

Track a screen:


Tracking all activities as screens:

this.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
    public void onActivityStarted(Activity activity) {

The Urban Airship SDK gives you the ability to track what screen a user views within the application, as well as how long the user stayed on that screen and the user's previous screen. These events then come through Urban Airship Connect and allow you to see the path that a user takes through an application, or to trigger actions based on a user visiting a particular area of the application.

When a new screen is tracked or when the application backgrounds, a screen tracking event will be generated. Normally, Analytics.trackScreen should be called in either Activity.onStart or Fragment.onStart, depending on how the application is built.

For applications where you only want to track activities, you can automate screen tracking with an activity life cycle listener.

Disabling Analytics

Disable analytics at runtime:


Features that depend on analytics being enabled may not work properly if it's disabled (reports, location segmentation, region triggers, push to local time).

If you do not wish to include analytics and reporting in your application, you can disable analytics in the Airship Config under the analyticsEnabled flag.

When analytics is disabled at runtime it will delete any locally stored events and prevent any events from uploading.

Android Preferences Screen

You can easily add Urban Airship preferences to the Android settings screen. The SDK provides the following preferences:

Enables/disables user notifications.
Enables/disables notification sounds.
Enables/disables notification vibration.
Enables/disables quiet time.
Sets the quiet time end.
Sets the quiet time start.
Enables/disables analytic events.
Displays the channel ID.
Displays the user ID.
Enables/disables location updates.
Enables/disables location updates from continuing in the background.

Location Targeting

The location component of the Urban Airship library is designed to be extremely flexible. You can use it to do all of your location tracking or if you want you can just use it when you're in need of a single location update and if neither one of those fits your needs, you can do your own location tracking and let us upload them to your dashboard for you. So, let's get started integrating location into your application so you can start making extremely relevant, targeted pushes to your users.



<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Enable Fused Location Services

dependencies {
  compile ''

In order to start using location in your app, you'll need to add a location permission to your AndroidManifest.xml.

If approximate locations aren't good enough, request android.permission.ACCESS_FINE_LOCATION instead to access the GPS.

Apps targeting Android Marshmallow (API 23) and later will prompt users to grant permissions at runtime, instead of install time. Since users can revoke permissions at any time from the app Settings screen, your app needs to check that it has the permissions it needs every time it runs. See Permissions for more details.

Using Urban Airship Location

Urban Airship Location exposes a very simple, high-level API for requesting location.

The Urban Airship SDK is compatible with Google Play Services' Fused Location Provider. Fused Location will automatically be used if Google Play Services is available on the device, is up to date, and the application was built with the Google Play Services dependency. Otherwise the standard Android location will be used, such as for Amazon devices. Google Play Services setup instructions can be found here.

Continuous Location Updates

Enabling location updates:

// Enable location updates

// Allow location updates to continue in the background

Listening for location updates:

// Create a listener
LocationListener listener = new LocationListener() {
    public void onLocationChanged(Location location) {
        Log.i("Location", "New user location " + location);

// Add the listener to UALocationManager

// Remove the listener when finished

Location updates are enabled or disabled by UALocationManager.setLocationUpdatesEnabled . Continuing updates in the background is controlled by UALocationManager.setBackgroundLocationAllowed . Listening for background locations now requires both location updates enabled and background location allowed.

Location updates can be listened for by instantiating or extending the LocationListener class:

Location Request Options

LocationRequestOptions options = new LocationRequestOptions.Builder()
        .setMinTime(5, TimeUnit.MINUTES)

// Set the default continuous location request options

Location request options are modeled after the Fused Location Provider by specifying high level needs instead of low level criteria. The location request options will automatically be converted to either criteria when using the standard Android Location APIs or to a LocationRequest when using Fused Location Provider.

The location request options for location updates will automatically default to LocationRequestOptions.PRIORITY_BALANCED_POWER_ACCURACY for request priority, 800 meters for minimum distance update interval and 5 minutes for minimum time update interval.

Single Location Requests


LocationCallback locationCallback = new LocationCallback() {
    public void onResult(Location location) {
        if (location != null) {
            Log.i("Location", "Single location request: " + location);
        } else {
            Log.i("Location", "Single request failed!");

Cancelable locationRequest = UAirship.shared()

// Optionally you can cancel the request and the callback will not be called

Single location requests can be made in addition to continuous location updates or by themselves to have more control over when location requests are made.

When a single location request is made, a PendingResult is returned. The PendingResult can be used to cancel the request or set a callback when the result is ready.

Recording Location


Any location update from Urban Airship's location module will automatically be recorded as a location event.

If you're using your own location tracking, you can still upload those events to Urban Airship so you can view them on your dashboard. Track the location by calling recordLocation on Analytics . The location will be automatically batched and uploaded so you can view it in your dashboard.

Google Pay

Create a pass request:

Field field = new Field.Builder()
        .setValue("text value")
        .setLabel("text label")

PassRequest passRequest = PassRequest.newBuilder()
        .setAuth("User Name", "Urban Airship API key")
        .setTemplateId("template ID")

Execute the pass request to fetch a pass object:

passRequest.execute(new Callback() {
                public void onResult(Pass pass) {
                  // Handle the pass

                public void onError(int errorCode) {
                    if (errorCode >= 500) {
                        // retry

Pass requests can be canceled at any time:


Prompt the user to add the pass:


The Urban Airship SDK provides tools to create Wallet passes and deep link them to Google Pay.

SDK Localization

The Urban Airship SDK provides localization for interactive notification buttons and the Message Center for the following languages: English, Chinese (Traditional), Chinese (Simplified), German, Hungarian, Slovak, Russian, Portuguese (Portugal), Portuguese (Brazil), French, Danish, Turkish, Norwegian, Romanian, Polish, Finnish, Dutch, Hindi, Spanish (Latin American), Spanish (Spain), Hebrew, Czech, Italian, Vietnamese, Thai, Japanese, Arabic, Korean, Malay, Indonesian, and Swedish.

To add translations for another language, copy the english strings.xml to the appropriate language resource folder. Translate it to the new language and the new language resource will be merged automatically. For more information, please see the Android documentation on resource merging and localization.