dotdigital Engagement Cloud

The dotdigital Engagement Cloud developer hub

Official dotdigital Engagement Cloud APIs documentation

Using the Android App Messaging SDK

A tutorial for adding the Android App Messaging SDK code to your app to allow your app users to receive push notifications from your Engagement Cloud account

Our Android App Messaging SDK uses Firebase Cloud Messaging (FCM) to send push notifications to your Android app users.

Our Android SDK is open source and can be found on Github here:

Basic sample apps can be found in Github here:

To embed in your native Android apps, complete the following tasks:

  1. Install the SDK
  2. Configure the SDK
  3. Initialise the SDK
  4. Optional: Change the icon or colour of your push notifications

Handling asynchronous requests

You can use either standard callbacks or observable streams to handle asynchronous requests. If you want to use observable streams, you need to add the RxJava library to your app. This tutorial explains how to use standard callbacks, but you can find a full sample of the RxJava code in the 'Android sample code' section.

Installing the SDK

  1. Add the App Messaging SDK to your module-level build.gradle file and change the minSDKVersion attribute to 16 using the snippet below:
defaultConfig {
...
minSdkVersion 16
...
}
Dependencies {
...
implementation 'com.comapi:foundation:1.2.0'
}

Seeing a 'Manifest merger' error?

The SDK has a minSDKVersion attribute of 16, your attribute must have a value of at least 16.

  1. Add the Google services plugin to your module-level build.gradle file using the snippet below:
apply plugin: 'com.google.gms.google-services'
  1. Add the following dependencies to your module-level build.gradle file using the snippet below:
implementation ('com.google.android.gms:play-services-base:15.0.1') {force = true}
implementation ('com.google.firebase:firebase-messaging:17.0.0') {force = true}

Sync Now

Remember to synchronise build.gradle files after making any changes.

Configuring the Android SDK

Before you can configure the Android SDK, you need the following:

  • The value of the API space ID field in Engagement Cloud
  • A class that creates a JWT token

  • Create a new instance of the ComapiConfig class, pass your API Space Id to the apiSpaceId() method, and an instance of the class that creates a JWT to the authenticator() method using the snippet below:

ComapiConfig config = new ComapiConfig() .apiSpaceId("<API_SPACE_ID>") .authenticator(new ChallengeHandler());

Displaying push notifications when the app is in the foreground

Push notifications are automatically displayed only while the app is in the background. These notifications are sent to the system tray and launch your app when users tap them.

If you want to display the push notification message while the app is in the foreground, do the following:

  1. Create a class that implements the pushMessageListener class (here, we've called the example class PushHandler). You'll need to decide what you want to do with the push notification and implement the logic by overriding the onMessageReceived() method. This method is called when a push notification is received while the app is in the foreground.

Deep links

If a push notification is delivered while the app is in the foreground, you can build your own in the 'onMessageReceived()` method that creates a link to a particular activity in your app.

public class PushHandler implements PushMessageListener {

    @Override
    public void onMessageReceived(RemoteMessage message) {
      // Check if message contains a notification payload.
        if (message.getNotification() != null) {
        Log.i("TAG", "Push notification: " + message.getNotification().getBody());
      // Do something with the message to notify the user
          // Example
          createNotificationChannel(context);
          Notification.Builder b = new Notification.Builder(context);
          b.setAutoCancel(true)
            .setDefaults(NotificationCompat.DEFAULT_ALL)
            .setWhen(System.currentTimeMillis())
            .setSmallIcon(R.drawable.common_google_signin_btn_icon_dark)
            .setContentTitle("foreground message")
            .setContentText(body)
            .setContentInfo("INFO");
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            b.setChannelId("test_channel_id1");
          }
          NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
          nm.notify(1, b.build());
        }
    }
}

private void createNotificationChannel(Context context) {
        // Create the NotificationChannel, but only on devices that have the Google API 26+ because the NotificationChannel class is new and not in supported in older libraries
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            CharSequence name = "test channel";
            String description = "some description";
            int importance = NotificationManager.IMPORTANCE_DEFAULT;
            NotificationChannel channel = new NotificationChannel("test_channel_id1", name, importance);
            channel.setDescription(description);
            // Register the channel with the system; you can't change the importance
            // or other notification behaviors after this
            NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }
}
  1. Pass your class to the pushMessageListener() on the ComapiConfig object
config.pushMessageListener(new PushHandler());

Configuring logs and proxy servers

You can set internal file logs, console logs, and network logs to the following levels. By default all log levels are set to WARNING:

  • OFF
  • FATAL
  • ERROR
  • WARNING
  • INFO
  • DEBUG

To change the log levels, add the following line to the ComapiConfig object and use the appropriate method on the LogConfig object:

.logConfig(new LogConfig().setFileLevel(LogLevel.DEBUG).setConsoleLevel(LogLevel.INFO).setNetworkLevel(LogLevel.ERROR));

You can also set a custom limit for the size of internal log files by calling the following method on the ComapiConfig object:

.logSizeLimitKilobytes(limit);

If your app connects through a proxy server, add the following line to the ComapiConfig object:

.apiConfiguration(new APIConfig().proxy("http://xx.xxx.xx.xxx:xxxx"));

Initialising the Android SDK

Where to initialise the Android SDK in the activity lifecycle

Initialisation needs to be performed in the onCreate() method of the Android Application class so that your app users' profiles don't change every time they open the app.

  1. After you've configured the SDK, import the com.google.firebase.FirebaseApp class into your java file, and initialise the Firebase SDK.
FirebaseApp.initializeApp(this);

2 Pass the ComapiConfig object to one of the following initialisation methods. These methods return a ComapiClient object that you can use to access the session and profile services, which are used to create and update the user's profile.

  • The initialiseShared() method: When you use this method, the SDK stores the 'ComapiClient' object, and you can access it at any time by calling the Comapi.getShared() method (Java) or the RxComapi.getShared() method (RxJava)
  • The initialise() method: When you use this method, you need to store the ComapiClient object yourself. The getShared() method is not available when you use this method.
public class MyApplication extends Application {

    @Override
    public void onCreate()
    {
        super.onCreate();
      
      	FirebaseApp.initializeApp(this);

        ComapiConfig config = new ComapiConfig();
        //<API space ID> string must be the same as the value of the 'API space ID' field in your push notification profile in Engagement Cloud. 
        config.apiSpaceId("<API space ID>");
        //Set handler for authentication challenges (SDK asks for a JWT token)
        config.authenticator(new ChallengeHandler());

        Comapi.initialiseShared(this, config, new Callback<ComapiClient>() {
            @Override
            public void success(final ComapiClient client) {
              //Use ComapiClient object to communicate with services
            }
            @Override
            public void error(Throwable t) {
							//Error
            }
        }); 

Changing the icon or colour of push notification

Our Android SDK uses Firebase Cloud Messaging (FCM) to send push notifications to your Android app users. As such, you can use the Android <meta-data> tag in your AndroidManifest.xml file to change the icon and colour of your push notifications.

<!-- Set icon used with incoming notification messages. This is used when no icon is set for the incoming notification message. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@mipmap/ic_launcher_round" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming notification message. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/colorAccent" />

Next steps

Now ensure your app passes an email address to the SDK for the app user to ensure they get a contact created in Engagement Cloud by following these instructions

Android Sample Code

package com.example.testapp;

import com.google.firebase.FirebaseApp;

import com.comapi.Comapi;
import com.comapi.ComapiClient;
import android.app.Application;

import com.comapi.Callback;
import com.comapi.ComapiConfig;
import com.comapi.Session;
import com.comapi.internal.network.ComapiResult;

import java.util.HashMap;
import java.util.Map;

public class MyApplication extends Application {

  @Override
  public void onCreate()
  {
    super.onCreate();
    
    FirebaseApp.initializeApp(this);

    ComapiConfig config = new ComapiConfig();
    //<API space ID> string must be the same as the value of the 'API space ID' field in your push notification profile in Engagement Cloud.
    config.apiSpaceId("<API space ID>");
    //Set the handler for authentication challenges (SDK asking for JWT token)
    config.authenticator(new AuthChallengeHandler());

    Comapi.initialiseShared(this, config, new Callback<ComapiClient>() {
      @Override
      public void success(final ComapiClient client) {
        if(client.getSession() != null && client.getSession().isSuccessfullyCreated()) {
          client.service().profile().getProfile(client.getSession().getProfileId(), new Callback<ComapiResult<Map<String, Object>>>() {
            @Override
            public void success(ComapiResult<Map<String, Object>> result) {
              Map <String, Object> additionalMap = new HashMap<>();
              //Add the user's email address to the profile
              additionalMap.put("email", "[email protected]");
              client.service().profile().patchMyProfile(additionalMap, result.getETag(), new Callback<ComapiResult<Map<String, Object>>>() {
                @Override
                public void success(ComapiResult<Map<String, Object>> result) {
                }
                @Override
                public void error(Throwable t) {
                }
              });
            }
            @Override
            public void error(Throwable t) {
            }
          }
                                               );
        } else {
          client.service().session().startSession(new Callback<Session>() {
            @Override
            public void success(Session result) {

            }

            @Override
            public void error(Throwable t) {

            }
          });
        }

      }

      @Override
      public void error(Throwable t) {
        //Error
      }
    });
  }
}
package com.example.testapp;

import android.app.Application;

import com.google.firebase.FirebaseApp;

import com.comapi.ComapiConfig;
import com.comapi.RxComapi;
import com.comapi.RxComapiClient;
import com.comapi.internal.network.ComapiResult;

import java.util.HashMap;
import java.util.Map;

import rx.Observable;
import rx.Subscriber;
import rx.functions.Func1;

public class MyApplication extends Application {

  @Override
  public void onCreate()
  {
    super.onCreate();
    
    FirebaseApp.initializeApp(this);

    RxComapi.initialise(
      this, new ComapiConfig()
      //<API space ID> string must be the same as the value of the 'API space ID' field in your push notification profile in Engagement Cloud.
      .apiSpaceId("<API space ID>")
      //Set the handler for authentication challenges (SDK asking for JWT token)
      .authenticator(new ChallengeHandler(getSharedPreferences(Const.PREFS_NAME, MODE_PRIVATE)))
    ).flatMap(new Func1<RxComapiClient, Observable<RxComapiClient>>() {
      @Override
      public Observable<RxComapiClient> call(final RxComapiClient client) {
        if (client.getSession() != null && client.getSession().isSuccessfullyCreated()) {  
            return Observable.fromCallable(new Callable<RxComapiClient>() {
              @Override
              public RxComapiClient call() throws Exception {
                return client;
              }
            });
          } else {
            return client.service().session().startSession().map(new Func1<Session, RxComapiClient>() {
              @Override
              public RxComapiClient call(Session session) {
                return client;
              }
            });
        }
      }
    }).flatMap(new Func1<RxComapiClient, Observable<ComapiResult<Map<String, Object>>>>() {
      @Override
      public Observable<ComapiResult<Map<String, Object>>> call(final RxComapiClient client) {
        if (!client.getSession().isSuccessfullyCreated()) {
          return Observable.error(new Exception("Failed to update profile"));
        }
        return client.service()
          .profile()
          .getProfile(client.getSession().getProfileId())
          .flatMap(new Func1<ComapiResult<Map<String, Object>>, Observable<ComapiResult<Map<String, Object>>>>() {
            @Override
            public Observable<ComapiResult<Map<String, Object>>> call(ComapiResult<Map<String, Object>> result) {
              Map<String, Object> additionalMap = new HashMap<>();
              //Add the user's email address to the profile
              additionalMap.put("email", "[email protected]");
              return client.service().profile().patchMyProfile(additionalMap, result.getETag());
            }
          }
                  );
      }
    }).subscribe(new Subscriber<ComapiResult<Map<String, Object>>>() {
      @Override
      public void onCompleted() {
      }
      @Override
      public void onError(Throwable e) {
      }
      @Override
      public void onNext(ComapiResult<Map<String, Object>> result) {
      }
    });
  }
}

Updated about 2 hours ago

Using the Android App Messaging SDK


A tutorial for adding the Android App Messaging SDK code to your app to allow your app users to receive push notifications from your Engagement Cloud account

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.