Android Notifications
Customizing notifications for Android
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.
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.
Creating custom notification channels
override fun onAirshipReady(airship : UAirship) {
// ...
val channelCompat = NotificationChannelCompat(
"customChannel",
"Breaking News!",
NotificationManagerCompat.IMPORTANCE_DEFAULT
)
airship.pushManager
.notificationChannelRegistry
.createNotificationChannel(channelCompat)
}
@Override
public void onAirshipReady(@NonNull UAirship airship) {
// ...
NotificationChannelCompat channelCompat = new NotificationChannelCompat(
"customChannel", "Breaking News!", NotificationManagerCompat.IMPORTANCE_DEFAULT);
airship.getPushManager()
.getNotificationChannelRegistry()
.createNotificationChannel(channelCompat);
}
The Airship SDK will fall back to the default notification channel if you set a notification channel ID that doesn’t exist, so make sure that you created one with the same ID.
Clearing Notifications
Notifications can be cleared manually by using standard Android APIs on the NotificationManager or NotificationManagerCompat classes.
Clear all Notifications
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.
Custom Provider Example
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)
// Make sure that your icon follows Google's Guidelines : a white icon with transparent background
.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 = requireNotNull(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 (message.alert.isNullOrEmpty()) {
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.
Extending AirshipNotificationProvider
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
}
}
Register the provider during takeOff
@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
Standard 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.
Example
// 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)
Categories