Overview
A push notification is an out-of-app alert that appears on the user’s screen when an important update occurs. Push notifications are a valuable way to provide your users with time-sensitive and relevant content or to re-engage them with your app.
Check out our help documentation for push best practices.
Braze sends push notifications to Android devices using Firebase Cloud Messaging (FCM).
Push notifications for Amazon FireOS use the Amazon Device Messaging (ADM) service rather than FCM. See the FireOS Push Integration instructions for details on enabling push notifications for FireOS apps.
For devices without Google services installed, Braze offers the option to send push through Baidu Cloud Push. Visit Baidu Cloud Push instructions for more details.
Registering for Push
Use Firebase Cloud Messaging (FCM) to register for push.
Automatic GCM registration is unavailable through the Braze SDK as a result of Google’s removal of support for GCM on May 29, 2019. If your app is currently supporting GCM, we advise that you speak to your development teams about transitioning to Firebase from GCM as soon as possible.
Firebase Integration
For a full sample of using Firebase with the Braze Android SDK, see our Firebase Push sample app.
Step 1: Enable Firebase
To get started, follow the instructions at Add Firebase to Your Android Project.
Next, add the Firebase Messaging dependency to your module’s build.gradle
:
1
2
implementation "com.google.firebase:firebase-core:${FIREBASE_CORE_VERSION}"
implementation "com.google.firebase:firebase-messaging:${FIREBASE_PUSH_MESSAGING_VERSION}"
Step 2: Configure Token Registration
Braze push notifications won’t work until a Firebase Cloud Messaging token (FCM registration token) is registered. FCM registration tokens can either be registered by the Braze SDK automatically (recommended) or manually registered. Tokens can be manually registered using the Appboy.registerAppboyPushMessages()
method.
Make sure to use your Firebase Sender ID. This is a unique numerical value created when you create your Firebase project, available in the Cloud Messaging tab of the Firebase console Settings pane. The sender ID is used to identify each sender that can send messages to the client app.
Option 1: Automatic Registration
To automatically register FCM registration tokens, enable automatic Firebase registration and set a Firebase Cloud Messaging Sender ID.
In your braze.xml
:
1
2
<bool translatable="false" name="com_appboy_firebase_cloud_messaging_registration_enabled">true</bool>
<string translatable="false" name="com_appboy_firebase_cloud_messaging_sender_id">your_fcm_sender_id_here</string>
Or in your AppboyConfig:
1
2
3
4
5
AppboyConfig appboyConfig = new AppboyConfig.Builder()
.setIsFirebaseCloudMessagingRegistrationEnabled(true)
.setFirebaseCloudMessagingSenderIdKey("YOUR FIREBASE SENDER ID HERE")
.build();
Appboy.configure(this, appboyConfig);
1
2
3
4
5
val appboyConfig = AppboyConfig.Builder()
.setIsFirebaseCloudMessagingRegistrationEnabled(true)
.setFirebaseCloudMessagingSenderIdKey("YOUR FIREBASE SENDER ID HERE")
.build()
Appboy.configure(this, appboyConfig)
If using a Firebase automatic registration, you can skip the manual options below.
Option 2: Manual Registration
We recommended you call Appboy.registerAppboyPushMessages()
from within your application onCreate()
method to ensure that push tokens are reliably delivered to Braze.
See the snippet below for an example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
final Context applicationContext = this;
FirebaseMessaging.getInstance().getToken().addOnCompleteListener(task -> {
if (!task.isSuccessful()) {
Log.w(TAG, "Exception while registering FCM token with Braze.", task.getException());
return;
}
final String token = task.getResult();
Appboy.getInstance(applicationContext).registerAppboyPushMessages(token);
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
FirebaseMessaging.getInstance().token.addOnCompleteListener { task: Task<String?> ->
if (!task.isSuccessful) {
Log.w(TAG, "Exception while registering FCM token with Braze.", task.exception)
return@addOnCompleteListener
}
val token = task.result
Appboy.getInstance(applicationContext).registerAppboyPushMessages(token)
}
}
}
While we highly recommend you register your FCM registration token in your application
onCreate()
, the token can be registered anywhere in your code.
Step 3: Migrate from GCM (Optional)
If migrating from using GCM to using Firebase with Braze, visit the GCM Migration Guide for instructions on how to properly switch to using Firebase in your app.
Step 4: Set Your Firebase Credentials
You need to input your Firebase Server Key and Sender ID into the Braze dashboard:
- On the app settings page (where your API keys are located), select your Android app.
- Enter your Firebase Server Key in the field labeled “Firebase Cloud Messaging Server Key” under the Push Notification Settings section.
- Enter your Firebase Sender ID in the field labeled “Firebase Cloud Messaging Sender ID” under the Push Notification Settings section.
If you’re not familiar with the location of your Firebase Server Key and Sender ID, follow these steps:
-
Login to the Firebase Developers Console
-
Select your Firebase project
-
Select Cloud Messaging under Settings and copy the Server Key and Sender ID:
Step 5: Remove Old Permissions
-
Braze no longer requires the following permissions if using Firebase:
1 2 3 4 5
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /> <permission android:name="YOUR-APPLICATION-PACKAGE-NAME.permission.C2D_MESSAGE" android:protectionLevel="signature"/> <uses-permission android:name="YOUR-APPLICATION-PACKAGE-NAME.permission.C2D_MESSAGE" />
Step 6: Remove Automatic Actions from your Application Class
If you have a custom Application subclass, ensure you do not have automatic logic that pings your servers in your class’s Application.onCreate()
lifecycle method. This will ensure that silent push notifications from Braze don’t cause unnecessary requests to your servers.
Displaying Push
After completing this section, you should be able to receive and display push notifications sent by Braze.
Step 1: Register Braze Firebase Messaging Service
Braze includes a service to handle push receipt and open intents. Our AppboyFirebaseMessagingService
class will need to be registered in your AndroidManifest.xml
.
1
2
3
4
5
6
<service android:name="com.appboy.AppboyFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
Braze’s notification code also uses AppboyFirebaseMessagingService
to handle open and click action tracking. This service must be registered in the AndroidManifest.xml
in order for that to function correctly. Also, keep in mind that Braze prefixes notifications from our system with a unique key to ensure we only render notifications sent from Braze’s systems. You may register additional services separately in order to render notifications sent from other FCM services.
If you already have a Firebase Messaging Service registered, do not complete this step. Instead, proceed to Using Your Own Firebase Messaging Service and complete the steps listed there.
Before Braze SDK 3.1.1, AppboyFcmReceiver
was used to handle FCM push. The AppboyFcmReceiver
class should be removed from your manifest and replaced with the above integration.
Implementation Example
- See
AndroidManifest.xml
in the Firebase Push sample app.
Using Your Own Firebase Messaging Service
If you already have a Firebase Messaging Service registered, you can pass RemoteMessage
objects to Braze via AppboyFirebaseMessagingService.handleBrazeRemoteMessage(). This method will only display a notification if the RemoteMessage
object originated from Braze and will safely ignore if not.
1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
if (AppboyFirebaseMessagingService.handleBrazeRemoteMessage(this, remoteMessage)) {
// This Remote Message originated from Braze and a push notification was displayed.
// No further action is needed.
} else {
// This Remote Message did not originate from Braze.
// No action was taken and you can safely pass this Remote Message to other handlers.
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
if (AppboyFirebaseMessagingService.handleBrazeRemoteMessage(this, remoteMessage)) {
// This Remote Message originated from Braze and a push notification was displayed.
// No further action is needed.
} else {
// This Remote Message did not originate from Braze.
// No action was taken and you can safely pass this Remote Message to other handlers.
}
}
}
Step 2: Ensure Small Icons Conform to Design Guidelines
For general information about Android notification icons, please see the Notifications Overview documentation.
Starting in Android N, you should update or remove small notification icon assets that involve color. The Android system (not the Braze SDK) ignores all non-alpha/transparency channels in action icons and in the notification small icon. In other words, Android will convert all parts of your notification small icon to monochrome with the exception of the transparent regions.
To properly create a notification small icon asset:
- Remove all color from the image except for white.
- All other non-white regions of the asset should be transparent.
A common symptom of an improper asset is the notification small icon rendering as a solid monochrome square. This is due to the Android system not being able to find any transparent regions in the notification small icon asset.
The icons pictured below are examples of properly designed icons:
Step 3: Configure Notification Icons
Specifying Icons in braze.xml
- Braze allows you to configure your notification icons by specifying drawable resources in your
braze.xml
:
1
2
<drawable name="com_appboy_push_small_notification_icon">REPLACE_WITH_YOUR_ICON</drawable>
<drawable name="com_appboy_push_large_notification_icon">REPLACE_WITH_YOUR_ICON</drawable>
Setting a small notification icon is required. If you do not set one, Braze will default to using the application icon as the small notification icon which may look suboptimal.
Setting a large notification icon is optional but recommended.
Specifying Icon Background Color
- The notification icon background color can be overriden in your
braze.xml
. If the color is not specified, the default background color is the same gray Lollipop uses for system notifications. Please see the example color override below:
1
<integer name="com_appboy_default_notification_accent_color">0xFFf33e3e</integer>
Step 4: Add Deep Links
Enabling Automatic Deep Link Opening
To enable Braze to automatically open your app and any deep links when a push notification is clicked, set com_appboy_handle_push_deep_links_automatically
to it’s default setting,true
, in your braze.xml
:
1
<bool name="com_appboy_handle_push_deep_links_automatically">true</bool>
This flag can also be set via runtime configuration:
1
2
3
4
AppboyConfig appboyConfig = new AppboyConfig.Builder()
.setHandlePushDeepLinksAutomatically(true)
.build();
Appboy.configure(this, appboyConfig);
1
2
3
4
val appboyConfig = AppboyConfig.Builder()
.setHandlePushDeepLinksAutomatically(true)
.build()
Appboy.configure(this, appboyConfig)
If you would like to custom handle deep links, you will need to create a BroadcastReceiver
that listens for push received and opened intents from Braze. See our section on Custom Handling Push Receipts and Opens for more information.
Creating Custom Deep Links
Please follow the instructions found within the Android Developer Documentation on Deep Linking if you have not already added deep links to your app. For information regarding what a deep link is, please see our FAQ Section.
Adding Deep Links
The Braze dashboard supports setting deep links or web URLs on push notifications that will be opened when the notification is clicked.
Customizing Back Stack Behavior
The Android SDK by default will place your host app’s main launcher activity in the back stack when following push deep links. Braze allows you to set a custom activity to open in the back stack in place of your main launcher activity or to disable the back stack altogether.
For example, to set an activity called YourMainActivity
as the back stack activity, see the following example using runtime configuration:
1
2
3
4
5
AppboyConfig appboyConfig = new AppboyConfig.Builder()
.setPushDeepLinkBackStackActivityEnabled(true)
.setPushDeepLinkBackStackActivityClass(YourMainActivity.class)
.build();
Appboy.configure(this, appboyConfig);
1
2
3
4
5
val appboyConfig = AppboyConfig.Builder()
.setPushDeepLinkBackStackActivityEnabled(true)
.setPushDeepLinkBackStackActivityClass(YourMainActivity.class)
.build()
Appboy.configure(this, appboyConfig)
See the equivalent configuration for your braze.xml
. Note that the class name must be the same as returned by Class.forName()
:
1
2
<bool name="com_appboy_push_deep_link_back_stack_activity_enabled">true</bool>
<string name="com_appboy_push_deep_link_back_stack_activity_class_name">your.package.name.YourMainActivity</string>
Step 5: Define Notification Channels
The Braze Android SDK supports Android Notification Channels. In the case that a Braze notification does not contain the ID for a notification channel or that a Braze notification contains an invalid channel ID, Braze will display the notification with the default notification channel defined in the SDK. Braze users make use of Android Notification Channels within the platform to group notifications.
To set the user facing name of the default Braze notification channel, please use AppboyConfig.setDefaultNotificationChannelName()
.
To set the user facing description of the default Braze notification channel, please use AppboyConfig.setDefaultNotificationChannelDescription()
.
You should ensure that any API campaigns with the Android Push Object parameter are updated to include the notification_channel
field. If this field is not specified, Braze will send the notification payload with the dashboard fallback channel ID.
Other than the default notification channel, Braze will not create any channels. All other channels must be programmatically defined by the host app and then entered into the Braze dashboard.
Step 6: Test Notification Display and Analytics
Testing Display
At this point, you should be able to see notifications sent from Braze. To test this, go to the Campaigns
section of your Braze dashboard and create a Push Notification
campaign. Choose Android Push
and design your message. Then click the eyeball in the composer to get the test sender. Enter the user id or email address of your current user and click Send Test
. You should see the push show up on your device.
For issues related to push display, see our Troubleshooting Guide.
Testing Analytics
At this point, you should also have analytics logging for push notification opens. To test this, see our Docs on creating a push campaign. Clicking on the notification when it arrives should result in the Direct Opens
on your campaign results page to increase by 1.
For issues related to push analytics, see our Troubleshooting Guide.
Testing From Command Line
If you’d like to test in-app and push notifications via the command-line, you can send a single notification through the terminal via cURL and the Messaging API. You will need to replace the following fields with the correct values for your test case:
YOUR_API_KEY
- available on the Developer Console pageYOUR_EXTERNAL_USER_ID
- available on the User Profile Search PageYOUR_KEY1
(optional)YOUR_VALUE1
(optional)
1
curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer " -d "{\"external_user_ids\":[\"YOUR_EXTERNAL_USER_ID\"],\"messages\":{\"android_push\":{\"title\":\"Test push title\",\"alert\":\"Test push\",\"extra\":{\"YOUR_KEY1\":\"YOUR_VALUE1\"}}}}" https://rest.iad-01.braze.com/messages/send
The above is an example for customers on the US-01
instance. If you are not on this instance please refer to our API documentation to see which endpoint to make requests to.
Customizing Your Integration
Custom Displaying Notifications
Step 1: Create your Custom Notification Factory
In some scenarios, you may wish to customize push notifications in ways that would be cumbersome or unavailable server side. To give you complete control of notification display, we’ve added the ability to define your own IAppboyNotificationFactory
to create notification objects for display by Braze.
If a custom IAppboyNotificationFactory
is set, Braze will call your factory’s createNotification()
method upon push receipt before the notification is displayed to the user. Braze will pass in a Bundle
containing Braze push data and another Bundle
containing custom key value pairs sent either via the dashboard or the messaging APIs:
Braze will pass in a BrazeNotificationPayload
containing data from the Braze push notification.
1
2
3
4
5
6
7
8
9
// Factory method implemented in your custom IAppboyNotificationFactory
@Override
public Notification createNotification(BrazeNotificationPayload brazeNotificationPayload) {
// Example of getting notification title
String title = brazeNotificationPayload.getTitleText();
// Example of retrieving a custom KVP ("my_key" -> "my_value")
String customKvp = brazeNotificationPayload.getAppboyExtras().getString("my_key");
}
1
2
3
4
5
6
7
8
// Factory method implemented in your custom IAppboyNotificationFactory
override fun createNotification(brazeNotificationPayload: BrazeNotificationPayload): Notification {
// Example of getting notification title
val title = brazeNotificationPayload.getTitleText()
// Example of retrieving a custom KVP ("my_key" -> "my_value")
val customKvp = brazeNotificationPayload.getAppboyExtras().getString("my_key")
}
You can return null
from your custom createNotification()
method to not show the notification at all, use AppboyNotificationFactory.getInstance().createNotification()
to obtain Braze’s default notification
object for that data and modify it before display, or generate a completely separate notification
object for display.
Braze push data keys are documented here.
Step 2: Set your Custom Notification Factory
To instruct Braze to use your custom notification factory, use the method on the Braze interface to set your IAppboyNotificationFactory
:
1
setCustomAppboyNotificationFactory(IAppboyNotificationFactory appboyNotificationFactory);
1
setCustomAppboyNotificationFactory(appboyNotificationFactory: IAppboyNotificationFactory)
The recommended place to set your custom IAppboyNotificationFactory
is in the Application.onCreate()
application lifecycle method (not activity). This will allow the notification factory to be set correctly whenever your app process is active.
Creating your own notification from scratch is an advanced use case and should be done only with thorough testing and deep understanding of Braze’s push functionality (you must, for example, ensure your notification logs push opens correctly).
To unset your custom IAppboyNotificationFactory
and return to default Braze handling for push, pass in null
to our custom notification factory setter:
1
setCustomAppboyNotificationFactory(null);
1
setCustomAppboyNotificationFactory(null)
Custom Handling For Push Receipts, Opens, Dismissals, and Key Value Pairs
Braze broadcasts custom intents when push notifications are received, opened, or dismissed. If you have a specific use case for these scenarios (such as the need to listen for custom key value pairs or proprietary handling of deep links), you will need to listen for these intents by creating a custom BroadcastReceiver
.
Step 1: Register your BroadcastReceiver
Register your custom BroadcastReceiver
to listen for Braze push opened and received intents in your AndroidManifest.xml
.
1
2
3
4
5
6
7
<receiver android:name="YOUR-BROADCASTRECEIVER-NAME" android:exported="false" >
<intent-filter>
<action android:name="${applicationId}.intent.APPBOY_PUSH_RECEIVED" />
<action android:name="${applicationId}.intent.APPBOY_NOTIFICATION_OPENED" />
<action android:name="${applicationId}.intent.APPBOY_PUSH_DELETED" />
</intent-filter>
</receiver>
Step 2: Create Your BroadcastReceiver
Your receiver should handle intents broadcast by Braze and launch your activity with them:
- It should subclass
BroadcastReceiver
and overrideonReceive()
. - The
onReceive()
method should listen for intents broadcast by Braze.- An
APPBOY_PUSH_RECEIVED
intent will be received when a push notification arrives. - An
APPBOY_NOTIFICATION_OPENED
intent will be received when a push notification is clicked by the user. - An
APPBOY_PUSH_DELETED
intent will be received when a push notification is dismissed (swiped away) by the user.
- An
- The receiver should perform your custom logic for each of these cases. If your receiver will open deep links, be sure to turn off automatic deep link opening by setting
com_appboy_handle_push_deep_links_automatically
tofalse
in yourbraze.xml
.
For a detailed custom receiver example, please see the below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class CustomBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = CustomBroadcastReceiver.class.getName();
@Override
public void onReceive(Context context, Intent intent) {
String packageName = context.getPackageName();
String pushReceivedAction = packageName + AppboyNotificationUtils.APPBOY_NOTIFICATION_RECEIVED_SUFFIX;
String notificationOpenedAction = packageName + AppboyNotificationUtils.APPBOY_NOTIFICATION_OPENED_SUFFIX;
String notificationDeletedAction = packageName + AppboyNotificationUtils.APPBOY_NOTIFICATION_DELETED_SUFFIX;
String action = intent.getAction();
Log.d(TAG, String.format("Received intent with action %s", action));
if (pushReceivedAction.equals(action)) {
Log.d(TAG, "Received push notification.");
} else if (notificationOpenedAction.equals(action)) {
AppboyNotificationUtils.routeUserWithNotificationOpenedIntent(context, intent);
} else if (notificationDeletedAction.equals(action)) {
Log.d(TAG, "Received push notification deleted intent.");
} else {
Log.d(TAG, String.format("Ignoring intent with unsupported action %s", action));
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class CustomBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val packageName = context.packageName
val pushReceivedAction = packageName + AppboyNotificationUtils.APPBOY_NOTIFICATION_RECEIVED_SUFFIX
val notificationOpenedAction = packageName + AppboyNotificationUtils.APPBOY_NOTIFICATION_OPENED_SUFFIX
val notificationDeletedAction = packageName + AppboyNotificationUtils.APPBOY_NOTIFICATION_DELETED_SUFFIX
val action = intent.action
Log.d(TAG, String.format("Received intent with action %s", action))
when (action) {
pushReceivedAction -> {
Log.d(TAG, "Received push notification.")
}
notificationOpenedAction -> {
AppboyNotificationUtils.routeUserWithNotificationOpenedIntent(context, intent)
}
notificationDeletedAction -> {
Log.d(TAG, "Received push notification deleted intent.")
}
else -> {
Log.d(TAG, String.format("Ignoring intent with unsupported action %s", action))
}
}
}
companion object {
private val TAG = CustomBroadcastReceiver::class.java.name
}
}
With notification action buttons, APPBOY_NOTIFICATION_OPENED
intents fire when buttons with opens app
or deep link
actions are clicked. Deep link and extras handling remains the same. Buttons with close
actions don’t fire APPBOY_NOTIFICATION_OPENED
intents and dismiss the notification automatically.
Step 3: Access Custom Key Value Pairs
Custom key value pairs sent either via the dashboard or the messaging APIs will be accessible in your custom broadcast receiver for whatever purpose you choose:
1
2
3
4
5
6
7
8
// intent is the Braze push intent received by your custom broadcast receiver.
String deepLink = intent.getStringExtra(Constants.APPBOY_PUSH_DEEP_LINK_KEY);
// The extras bundle extracted from the intent contains all custom key value pairs.
Bundle extras = intent.getBundleExtra(Constants.APPBOY_PUSH_EXTRAS_KEY);
// example of getting specific key-value pair from the extras bundle.
String myExtra = extras.getString("my_key");
1
2
3
4
5
6
7
8
// intent is the Braze push intent received by your custom broadcast receiver.
val deepLink = intent.getStringExtra(Constants.APPBOY_PUSH_DEEP_LINK_KEY)
// The extras bundle extracted from the intent contains all custom key value pairs.
val extras = intent.getBundleExtra(Constants.APPBOY_PUSH_EXTRAS_KEY)
// example of getting specific key-value pair from the extras bundle.
val myExtra = extras.getString("my_key")
Braze push data keys are documented here.