Android push notifications

Android push setup, push services, notification channels, and customization

See more on push notification services, Android Notification Channels, and customizing push notifications:

🚧

Adaptive icons warning (Resolved in Leanplum Android SDK 4.2.2+)

Using adaptive icons for push on Android Oreo without a fallback icon can cause problems that may require a factory reset of the device. Please add a regular icon with name leanplum_default_push_icon.png to your drawable folder. Google issue: https://issuetracker.google.com/issues/68716460

Using push notification services

Follow the setup instructions in the Android SDK setup for basic push functionality. Leanplum supports Firebase Cloud Messaging (FCM).

Generally, you can configure your Android project to use Leanplum push services with other custom or third-party push notification services by creating custom classes that extend the correct Leanplum push messaging classes.

Create a custom class to receive push messages

If you want to create a custom class to define the behavior for your project after receiving a Push Message, or you are using Leanplum together with other libraries, follow the below steps.
If you want to customize the notification appearance, use our push notification customizer as described here.

Depending on which version of the Leanplum SDK you are using, the implementation may look different. In most cases, we recommend using the latest version (5.7.0 ). In that case, follow the below for Android SDK 5.5.0.
However if you use or require a previous version of the SDK, use this guide.

Leanplum Android SDK 5.5.0+

Starting with the Leanplum Android SDK v5.5.0+, you can now use your own implementation of FirebaseMessagingService with Leanplum push services as long as you call our LeanplumFirebaseServiceHandler handler class.

To implement this with Leanplum, you will need to:

STEP 1:

Use our code from the LeanplumPushFirebaseMessagingService. There is no need to inherit from our service since you can execute the Leanplum code through the LeanplumFirebaseServiceHandler.

STEP 2:

Copy the following code into your manifest file. Note: You will need to change the service name above to include your service name.

<!-- Disable the default Leanplum FCM message handling service -->
<service
  xmlns:tools="http://schemas.android.com/tools"
  android:name="com.leanplum.LeanplumPushFirebaseMessagingService"
  android:enabled="false"
  tools:replace="android:enabled"/>

<!-- Add your custom FCM message handling service -->
<service
  android:name="your.package.Copy_of_LeanplumPushFirebaseMessagingService"
  android:enabled="true"
  android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT"/>
    </intent-filter>
</service>

👍

When to Call The LeanplumFirebaseServiceHandler method

When using the LeanplumFirebaseServiceHandler methods to call Leanplum, you will need to call it in the following 2 use cases:

  • When a new token is generated (onNewToken)
  • When a push notification is received (onMessageReceived).

Older Leanplum Android SDK versions (below 5.5.0)

For Firebase, the new class .Custom_FirebaseMessagingService must extend the LeanplumPushFirebaseMessagingService class (which is extending FirebaseMessagingService).

public class Custom_FirebaseMessagingService extends LeanplumPushFirebaseMessagingService {
    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
       super.onMessageReceived(remoteMessage);
        Log.i("### ", "Firebase message received");
    }
}

We will invoke this custom class later with a service in the Android Manifest.

📘

The custom class you create must include the onMessageReceived method. This will need to override its parent method but still call super.onMessageReceived(). This will make sure the Leanplum code in the extended class is executed when the push notification is received. You can place any custom code within this method after this call.

Invoke the custom class in your Manifest

Once you have implemented the Leanplum SDK, modified your Application class and AndroidManifest.xml file as documented in the Android Quick Start, you will still need to make a few modifications in your Manifest to use our push services.

To accomplish this, you will need to edit the service com.google.firebase.MESSAGING_EVENT so that it invokes the .Custom_FirebaseMessagingService class.

This will require you change the android:name attributes to point to your custom classes as below

<service
    <!-- android:name="com.leanplum.LeanplumPushFirebaseMessagingService" -->
    android:name=".Custom_FirebaseMessagingService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

GitHub sample project for push services

A sample Firebase project is available here, and you can see its manifest file here.

Android Push Payload

Below is a sample push notification payload sent from Leanplum on FCM:

{lp_version=1, lp_channel={"importance":3,"name":"rondo-channel","id":"123"}, 
lp_message=Click to open website, lp_occurrence_id=cc79912a-1e57-4c0f-ac39-7e71690b4123,
_lpm=6383058347425123, _lpx={"__name__":"Open URL","URL":"https://google.com"}, lp_sent_time=1620913353867}

Android Notification Channels

Starting in Android 8.0 (Oreo), notification channels were introduced to give developers more control over push notification customization and management.

These Android Notification channels allow app developers to categorize their push notifications based on the type of content they are trying to send to users. Depending on the channel, you can modify the color, the sound and vibration pattern for each notification category. Additionally you can customize how prominently the notification appears on the user's device.

You can see more from Android's documentation here.

If your audience includes Android 8 users, you must implement one or more notification channels in order to send notifications to your users. Sending a push notification to Android 8 users without specifying a valid notifications channel will cause the message to fail to post, and the system will log an error.

To set up the notification channels in Leanplum, follow the below steps.

STEP 1. Set up Android Notification Channels in Leanplum

Notification Channels must be added via our specific API calls. You can add, delete, or modify these notification channels.

📘

Add/Edit/Delete Notification Channels

See our API docs for more on the methods addAndroidNotificationChannel and deleteAndroidNotificationChannel.

STEP 2. Send a push notification with Android Notification Channels

Once a notification channel has been added via our API, your new channel should be accessible for use in our Message and Campaign composers.

To select your desired channel from the dashboard, the Notification channel setting should be in from the Advanced options section in the push notifications settings of both the message and campaign composer.

This is in the Edit window of the push notification action.This is in the Edit window of the push notification action.

This is in the Edit window of the push notification action.

STEP 3 (optional). See all notification channels defined in Leanplum

Once you have set all the notification channels in Leanplum, you can pull a full list of your notification channels via our API docs with the getAndroidNotificationChannels API call.

Customizing push notifications

Android push notifications can also be customized with the Leanplum SDK. To customize the appearance of your push notifications, you can use the LeanplumPushService.setCustomizer method in your Application class's onCreate method. After you have implemented this method, you can perform any customizations you want to the NotificationCompat object.

Additionally, you have the option to use our customizer, which will notify you of incoming pushes from Leanplum. This will allow you to access the notification's properties, such as the message (bundle.getString("lp_message")) or other any custom key:value pairs you defined in the Leanplum dashboard under the Push Notification advanced options. Found under Advanced Options > Data

For a detailed example, see our guide below.

🚧

It's a good practice to show additional information or navigate to the correct part of your app when users open your push notifications. You can do that using Leanplum's in-app messaging, which integrates nicely with push notifications.

Setting the Push Notification Customizer

Sample project: Android sample projects here.

By default, it is possible to apply the Leanplum notification customizer once the notification is received in the app. This means that every notification will be by default customized once received in the app.

The LeanplumPushService.setCustomizer has to be placed inside the project Application class. In this way, we are basically telling our app to apply the customizer to every Push Notification we receive for the app. The customizer is passing the builder class which is used to set elements like icons or images.

Let's assume I'd like to change the smallIcon (included in the project Drawables folder) of my incoming Push Notifications.

I'd need to add the following code to the Application class:

LeanplumPushService.setCustomizer(new LeanplumPushNotificationCustomizer() {
@Override
public void customize(NotificationCompat.Builder builder, Bundle notificationPayload) {
// Setting a custom smallIcon included in the Drawable folder
builder.setSmallIcon(R.drawable.atest);
}
*   @Override
public void customize(Notification.Builder builder, Bundle notificationPayload, @Nullable Notification.Style notificationStyle) {
// leave this method empty
}
});

Or, if I wanted to support 2 lines of text in the BigPicture style, I'd need to pass true as the second argument of setCustomizer and include my custom code in the overloaded customize method.

LeanplumPushService.setCustomizer(new LeanplumPushNotificationCustomizer() {
  @Override
  public void customize(NotificationCompat.Builder builder, Bundle notificationPayload) {
    // leave this method empty
  }
  
@Override
public void customize(Notification.Builder builder, Bundle notificationPayload, @Nullable Notification.Style notificationStyle) {
    if (Build.VERSION.SDK_INT > 16) {
      if (notificationStyle != null && notificationStyle instanceof Notification.BigPictureStyle) {
        // Create largeIconBitmap
        ((Notification.BigPictureStyle) notificationStyle).bigLargeIcon(largeIconBitmap);
      }
    }
  }
}, true);

In general, within the LeanplumPushService.setCustomizer we can use what the NotificationCompat.Builder class could allow us to customize the Push Notification (see also Android docs here https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html).

Using the Notification payload

With the LeanplumPushService.setCustomizer we are also passing the Bundle notificationPayload object, which would come in hand if we want to get custom Data being included in the Push Notification payload.

In this way, we can grab key-value pairs being set in the Advanced options/Data fields in the Message composition in the Leanplum Dashboard.

A common use would be to set a String URL and use it to switch which images you want to be displayed in the Push Notification.

For example, if we'd like to customize the Push Notification Large Icon, we can pass the new Icon image via URL in the Push Notification payload by adding a String with the URL value in the Message on the Dashboard, like in the image:

Then, inside the customizer, we can get the largeImageURL value, retrieve the image and set it as the Large Icon in this way:

String urlLargeImageString = notificationPayload.getString("largeImageURL");

URL urlLargeImageURL = null;
try {
    urlLargeImageURL = new URL(urlLargeImageString);
} catch (MalformedURLException e) {
    e.printStackTrace();
}

Bitmap largeImage = null;
try {
    largeImage = BitmapFactory.decodeStream(urlLargeImageURL.openConnection().getInputStream());
} catch (java.io.IOException e) {
    e.printStackTrace();
}

builder.setLargeIcon(largeImage);

This approach is valid for also other customizable elements.