Airship’s SDK provides a simple interface for managing push notifications within your Android application.
Enabling User Notifications
The 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.
UAirship.shared().getPushManager().setUserNotificationsEnabled(true);
UAirship.shared().pushManager.userNotificationsEnabled = true
Notification Channels
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 the notification channel can also be set per message by specifying the channel’s ID in the Push API.
Quiet time, sound, and vibration settings have been superseded by notification channels on Android O and newer devices.
Compat Notification Channels
Notification channel compat allows you to define notification channels for all Android versions. For pre-O Android devices, the Airship SDK will apply the notification channel settings on the notification before posting. This allows an app to define channels and use them across all devices.
@Override
public void onAirshipReady(@NonNull UAirship airship) {
...
NotificationChannelCompat channelCompat = new NotificationChannelCompat("customChannel",
"Breaking News!",
NotificationManagerCompat.IMPORTANCE_DEFAULT);
airship.getPushManager()
.getNotificationChannelRegistry()
.createNotificationChannel(channelCompat);
}
override fun onAirshipReady(airship : UAirship) {
...
val channelCompat = NotificationChannelCompat("customChannel",
"Breaking News!",
NotificationManagerCompat.IMPORTANCE_DEFAULT)
airship.pushManager
.notificationChannelRegistry
.createNotificationChannel(channelCompat)
}
Listening For Notification Events
Set the NotificationListener
during takeOff to be notified of any notification activity
from the Airship SDK.
@Override
public void onAirshipReady(@NonNull UAirship airship) {
...
// Notification listener
airship.getPushManager().setNotificationListener(new NotificationListener() {
@Override
public void onNotificationPosted(@NonNull NotificationInfo notificationInfo) {
Log.i(TAG, "Notification posted. Alert: " + notificationInfo.getMessage().getAlert() + ". NotificationId: " + notificationInfo.getNotificationId());
}
@Override
public boolean onNotificationOpened(@NonNull NotificationInfo notificationInfo) {
Log.i(TAG, "Notification opened. Alert: " + notificationInfo.getMessage().getAlert() + ". NotificationId: " + notificationInfo.getNotificationId());
// Return false here to allow Airship to auto launch the launcher activity
return false;
}
@Override
public boolean onNotificationForegroundAction(@NonNull NotificationInfo notificationInfo, @NonNull NotificationActionButtonInfo actionButtonInfo) {
Log.i(TAG, "Notification foreground action. Button ID: " + actionButtonInfo.getButtonId() + ". NotificationId: " + notificationInfo.getNotificationId());
return false;
}
@Override
public void onNotificationBackgroundAction(@NonNull NotificationInfo notificationInfo, @NonNull NotificationActionButtonInfo actionButtonInfo) {
Log.i(TAG, "Notification background action. Button ID: " + actionButtonInfo.getButtonId() + ". NotificationId: " + notificationInfo.getNotificationId());
}
@Override
public void onNotificationDismissed(@NonNull NotificationInfo notificationInfo) {
Log.i(TAG, "Notification dismissed. Alert: " + notificationInfo.getMessage().getAlert() + ". Notification ID: " + notificationInfo.getNotificationId());
}
});
}
override fun onAirshipReady(airship : UAirship) {
...
// Notification listener
airship.pushManager.setNotificationListener(object : NotificationListener {
override fun onNotificationPosted(notificationInfo: NotificationInfo) {
Log.i(TAG, "Notification posted. Alert: ${notificationInfo.message.alert}. NotificationId: ${notificationInfo.notificationId}")
}
override fun onNotificationOpened(notificationInfo: NotificationInfo): Boolean {
Log.i(TAG, "Notification opened. Alert: ${notificationInfo.message.alert}. NotificationId: ${notificationInfo.notificationId}")
// Return false here to allow Airship to auto launch the launcher activity
return false
}
override fun onNotificationForegroundAction(notificationInfo: NotificationInfo, actionButtonInfo: NotificationActionButtonInfo): Boolean {
Log.i(TAG, "Notification foreground action. Button ID: ${actionButtonInfo.buttonId}. NotificationId: ${notificationInfo.notificationId}")
return false
}
override fun onNotificationBackgroundAction(notificationInfo: NotificationInfo, actionButtonInfo: NotificationActionButtonInfo) {
Log.i(TAG, "Notification background action. Button ID: ${actionButtonInfo.buttonId}. NotificationId: ${notificationInfo.notificationId}")
}
override fun onNotificationDismissed(notificationInfo: NotificationInfo) {
Log.i(TAG, "Notification dismissed. Alert: ${notificationInfo.message.alert}. NotificationId: ${notificationInfo.notificationId}")
}
})
}
Listening For Push Messages
In addition to the NotificationListener
, you can listen to all incoming push messages received
by the SDK by adding a PushListener
.
@Override
public void onAirshipReady(@NonNull UAirship airship) {
...
// Push listener
airship.getPushManager().addPushListener((message, notificationPosted) -> {
Log.i(TAG, "Received push message. Alert: " + message.getAlert() + ". posted notification: " + notificationPosted);
});
}
override fun onAirshipReady(airship : UAirship) {
...
// Push listener
airship.pushManager.addPushListener { message, notificationPosted ->
Log.i(TAG, "Received push message. Alert: ${message.alert}. posted notification: $notificationPosted")
}
}
Clearing Notifications
Notifications can be cleared manually by using standard Android APIs on the NotificationManager or NotificationManagerCompat classes.
NotificationManagerCompat.from(context).cancelAll();
NotificationManagerCompat.from(context).cancelAll()
Customizing Push Notifications
The AirshipNotificationProvider
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 implements the NotificationProvider .
The Airship SDK uses the AirshipNotificationProvider . With this provider, the standard Android Notification layout will use the application’s title and icon. A default big text style will be applied for all notifications.

Custom Notification Provider
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.
public class CustomNotificationFactory implements NotificationProvider {
@WorkerThread
@NonNull
@Override
public NotificationArguments onCreateNotificationArguments(@NonNull Context context, @NonNull PushMessage message) {
String channel = message.getNotificationChannel("defaultChannel");
return NotificationArguments.newBuilder(message)
.setNotificationChannelId(channel)
.setNotificationId(message.getNotificationTag(), NotificationIdGenerator.nextID())
.build();
}
@WorkerThread
@NonNull
@Override
public NotificationResult onCreateNotification(@NonNull Context context, @NonNull NotificationArguments arguments) {
PushMessage message = arguments.getMessage();
// do not display a notification if there is not an alert
if (UAStringUtil.isEmpty(message.getAlert())) {
return NotificationResult.cancel();
}
// Build the notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setContentTitle("Notification title")
.setContentText(message.getAlert())
.setAutoCancel(true)
.setSmallIcon(R.drawable.notification_icon);
// Notification action buttons
builder.extend(new ActionsNotificationExtender(context, message, notificationId));
return NotificationResult.notification(builder.build);
}
@WorkerThread
public void onNotificationCreated(@NonNull Context context, @NonNull Notification notification, @NonNull NotificationArguments arguments) {
// Called after the notification is built, right before posting the notifications. Apply any global
// defaults to the notification
}
}
public class CustomNotificationFactory : NotificationProvider {
@WorkerThread
override fun onCreateNotificationArguments(context: Context, message: PushMessage): NotificationArguments {
val channel = message.getNotificationChannel("defaultChannel")
return NotificationArguments.newBuilder(message)
.setNotificationChannelId(channel!!)
.setNotificationId(message.notificationTag, NotificationIdGenerator.nextID())
.build()
}
@WorkerThread
override fun onCreateNotification(context: Context, arguments: NotificationArguments): NotificationResult {
val message = arguments.message
// do not display a notification if there is not an alert
if (UAStringUtil.isEmpty(message.alert)) {
return NotificationResult.cancel()
}
// Build the notification
val builder = NotificationCompat.Builder(context)
.setContentTitle("Notification title")
.setContentText(message.alert)
.setAutoCancel(true)
.setSmallIcon(R.drawable.notification_icon)
// Notification action buttons
builder.extend(ActionsNotificationExtender(context, message, notificationId))
return NotificationResult.notification(builder.build())
}
@WorkerThread
override fun onNotificationCreated(context: Context, notification: Notification, arguments: NotificationArguments) {
// Called after the notification is built, right before posting the notifications. Apply any global
// defaults to the notification
}
}
For simple modifications, it is recommended to extend the AirshipNotificationProvider
instead to ensure
all Airship push features continue to work.
public class CustomNotificationFactory extends AirshipNotificationProvider {
public CustomNotificationFactory(@NonNull Context context, @NonNull AirshipConfigOptions configOptions) {
super(context, configOptions);
}
@WorkerThread
@NonNull
@Override
protected NotificationCompat.Builder onExtendBuilder(@NonNull Context context,
@NonNull NotificationCompat.Builder builder,
@NonNull NotificationArguments arguments) {
builder = super.onExtendBuilder(context, builder, arguments);
// Apply any defaults to the builder
return builder;
}
}
public class CustomNotificationFactory(context: Context, configOptions: AirshipConfigOptions) : AirshipNotificationProvider(context, configOptions) {
@WorkerThread
override fun onExtendBuilder(context: Context,
builder: NotificationCompat.Builder,
arguments: NotificationArguments): NotificationCompat.Builder {
val newBuilder = super.onExtendBuilder(context, builder, arguments)
// Apply any defaults to the builder
return newBuilder
}
}
@Override
public void onAirshipReady(UAirship airship) {
airship.getPushManager()
.setNotificationProvider(new CustomDefaultNotificationProvider());
}
override fun onAirshipReady(airship : UAirship) {
airship.pushManager.notificationProvider = CustomDefaultNotificationProvider()
}
Available Notification Extenders
The SDK also provides several notification builder extenders to help support Android Push features.
- ActionsNotificationExtender
- Supports Android Notification Action Button API features.
- PublicNotificationExtender
- Supports Public Notification API features.
- StyleNotificationExtender
- Supports Android style API features.
- WearableNotificationExtender
- Supports Android Wear API features.
Interactive Notifications
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)
If you want to define a custom Interactive Notification type, you must register a new notification action button group.
Airship reserves category IDs prefixed with ua_
. Any custom groups
with that prefix will be dropped.
Custom NotificationActionButtonGroups are supported by registering the groups with the PushManager right after UAirship.takeOff using the PushManager.addNotificationActionButtonGroup method.
// Define actions for the group
NotificationActionButton hiButtonAction = new NotificationActionButton.Builder("hi")
.setLabel(R.string.hi)
.setIcon(R.drawable.your_icon_file)
.setPerformsInForeground(true)
.build();
NotificationActionButton byeButtonAction = new NotificationActionButton.Builder("bye")
.setLabel(R.string.bye)
.setIcon(R.drawable.your_icon_file)
.setPerformsInForeground(true)
.build();
// Define the group
NotificationActionButtonGroup buttonGroup = new NotificationActionButtonGroup.Builder()
.addNotificationActionButton(hiButtonAction)
.addNotificationActionButton(byeButtonAction)
.build();
// Add the custom group
airship.getPushManager().addNotificationActionButtonGroup("custom group", buttonGroup);
// Define actions for the group
val hiButtonAction: NotificationActionButton = NotificationActionButton.Builder("hi")
.setLabel(R.string.hi)
.setIcon(R.drawable.your_icon_file)
.setPerformsInForeground(true)
.build()
val byeButtonAction: NotificationActionButton = NotificationActionButton.Builder("bye")
.setLabel(R.string.bye)
.setIcon(R.drawable.your_icon_file)
.setPerformsInForeground(true)
.build()
// Define the group
val buttonGroup = NotificationActionButtonGroup.Builder()
.addNotificationActionButton(hiButtonAction)
.addNotificationActionButton(byeButtonAction)
.build()
// Add the custom group
airship.pushManager.addNotificationActionButtonGroup("custom group", buttonGroup)
Android-Specific Payloads
Android has several features not present in other platforms. These can be specified
in the Android override in the notification
object.