This document, source code, and resulting compiled library (SDK) is intended to be used in conjunction with Marketing Suite. Use of the SDK is only supported after approval from Marketing Suite Client Developer Relations, and your account manager.
CCMP enables marketers to target mobile devices running native applications for iOS and Android. The Android platform uses Firebase, the successor to Google Cloud Messaging (GCM). With push notifications, there are three parties in play: CCMP, Firebase, and the user's device with an app installed. The basic flow is as follows for Push Notifications.
- After the app starts, the app contacts Firebase and requests a device token.
- The device token is sent back to the device.
- The device token is sent to CCMP along with an App ID and Customer ID.
- CCMP registers the device token with the App ID and Customer ID, and sends back a Push Registration ID (PRID).
- CCMP will then launch campaigns intending to target devices that have been registered with Push Notifications through Firebase.
- Firebase pushes out the notifications to the devices.
- After the user taps on the notification on the device, the app will notify CCMP that the app was opened from a Notification.
To make all this work, associations need to be set up between all three parties. This guide will walk you through these steps.
- Create or open a new project in Android Studio
- Create a Project on Firebase
- Register an App on Firebase
- Integrate the SDK with an App
- Adding the App to CCMP
- EMSMobileSDK Methods and Properties
- Sequence Diagram
-
If you have an existing project you intend to use for Push Notification, open this project, Otherwise create a new project in Android Studio.
-
Once the project is opened, open the project App level Gradle Script. Copy the value next to applicationID in the script, which in the case below is "experian.mycoolapp".
This Application ID is needed to register a new app with Firebase.
- Also, insure that the Google Repositories are installed. From the Tools menu, select Android -> SDK Manager. Select the SDK Tools tab, then expand Support Repository. Check Google Repository and click OK.
A Firebase project is a collection of apps that can use a variety of Google API's including push notifications. If you do not already have a Firebase project you intend to use with push notifications, you'll need to create one. Othewise, select the project and proceed to Register an App on Firebase.
-
Go to https://consoled.firebase.google.com and logon to Firebase with a Google account
-
Select Create a New Project.
- Enter a new name in the Project Name field, then select Create Project.
- On Firebase in the project you intend to use, select Add Firebase to your Android app.
- On the dialog, paste the application ID from the app Gradle script into the Package name field, then optionally supply a App nickname for the app. Then click Add App. This will add the app and download a GoogleServices.json file to your computer.
Note: On the next screen gives instructions on how to finish integrating Firebase into your app. These instructions will be amended with additional information below. Click Continue, then Finish on the last screen to add the app to the Firebase Project.
- In Android Studio, open the Project Gradle script labeled build.gradle (Project: yourProject) and add classpath 'com.google.gms:google-services:3.0.0' the to the project dependencies.
dependencies {
classpath 'com.android.tools.build:gradle:3.1.3'
classpath 'com.google.gms:google-services:4.0.1'
...
- Open the App Module Gradle script labeled build.gradle (Module: app) and add the following dependencies to the bottom of the app dependencies section.
implementation 'com.google.firebase:firebase-messaging:10.0.1'
implementation 'com.google.firebase:firebase-core:11.8.0
implementation 'com.android.volley:volley:1.0.0'
implementation 'org.apache.directory.studio:org.apache.commons.io:2.4'
- Add apply plugin: 'com.google.gms.google-services' to the very bottom othe App Module Gradle file. The App Module Gradle script should look something like this at the end.
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'com.android.support:appcompat-v7:26.1.0'
testImplementation 'junit:junit:4.12'
releaseImplementation "com.experian.mobilesdk:EMSMobileSDK:$sdk_version"
implementation 'com.google.firebase:firebase-core:11.8.0'
implementation 'com.google.firebase:firebase-messaging:11.8.0'
implementation 'com.android.volley:volley:1.0.0'
}
apply plugin: 'com.google.gms.google-services'
- On the root of the app module, copy and paste the GoogleServices.json file that was downloaded from Firebase.
- Android Studio will display a banner asking you to resync the Gradle Scripts. Click Sync Now
- Right click on the app module and select Open Module Settings. Click the Dependencies tab, click the + icon, then select Module Dependency.
Back in Android Studio with the project open, you can now add the SDK to the App.
-
Copy the ExperianMobileSDK.aar file into the libs folder in the app. This folder is usually found relative to the project at "Project\app\libs", such as "MyCoolApp\app\libs" in the running example.
-
From the File menu, select New -> New Module.
-
From the New Module gallery, select Import JAR/AAR Package and click Next.
-
On the next screen, click the ellipses (...) icon.
-
Find ExperianMobileSDK.aar file in the app\libs folder, then click OK.
- Android Studio will populate the fields. Click Finish to complete the task.
-
- Select EMSMobileSDK and then click OK.
-
On the Main Activity for the App, add import experian.mobilesdk.*; to the imports at the top of the MainActivity.java.
-
Paste the following code into the OnCreate method.
EMSMobileSDK.Default().init(
getApplicationContext(),
"APP ID GOES HERE", //The Application ID from CCMP
100, //Customer ID
Region.NORTH_AMERICA //The CCMP Region);
You should have a MainActivity.java that looks similar to this:
import experian.mobilesdk.*;
public class MainActivity extends AppCompatActivity implements IEMSPRIDCallback {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Initialize the SDK with the app context, the app's calling intent, the AppID from CCMP, the Custonmer ID, and the Region.
EMSMobileSDK.Default().init(
getApplicationContext(),
"APP ID GOES HERE",
100,
Region.NORTH_AMERICA_SANDBOX);
In order to add an app to CCMP, you'll need to have the package name on Google.
- On CCMP, select the Globe icon, then select Mobile Push Application Groups.
- Either select an existing group or create a new group.
- Create a new group by selecting the + icon, typing in a name for the group on the dialog, then click Save New Item.
* Either select the newly created group or the existing group in the list of Application Groups.
- On the Firebase Console, select the Project that you are registering from the dashboard.
-
On the Project dashboard, copy the name of the application you want to integrate with CCMP.
-
Copy the name of the application you want to use with CCMP.
- Back on CCMP, Click, Add Application.
-
Select Android GCM next to Platform and paste the application name in the Application Name field.
-
Back on Firebase, select the context menu for the application, then select Settings.
- Select the Cloud Messaging tab, then copy the Server Key.
- On CCMP, paste the **Server Key **into the Google API Key, then click Save.
- Copy the Application ID generated by the application.
-
Paste the key into the init method for the SDK.
import experian.mobilesdk.*; public class MainActivity extends AppCompatActivity implements IEMSPRIDCallback { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //Initialize the SDK with the app context, the app's calling intent, the AppID from CCMP, the Custonmer ID, and the Region. EMSMobileSDK.Default().init( getApplicationContext(), "df0cde1c-81a7-48d4-b65d-3b1f83e4c746", 100, Region.NORTH_AMERICA_SANDBOX);
The SDK offers a method to handle deep links from Marketing Suite, the call to EMSMobileSDK.Default().HandleDeepLink will parse the incoming deep link URL and returns the original URL along with the Deep Link Parameter entered on CCMP (if any)
Note: You first need to configure the app to handle universal links, add in the manifest.xml the following intent-filter. The values in the intent-filter here are used as an example, in this case "rts.eccmp.com" which will handle links of the type "http://rts.eccmp.com"
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="http"
android:host="rts.eccmp.com"/>
</intent-filter>
protected void onCreate(Bundle savedInstanceState) {
...
Intent intent = getIntent();
if(intent.getAction() == "android.intent.action.VIEW"){
EMSDeepLink deepLink = EMSMobileSDK.Default().HandleDeepLink(intent);
//deeplink.getDeepLinkParameter() - dl parameter from CCMP if any; example value: "param"
//deeplink.getDeepLinkUrl() - Original Deep link URL; example value: "http://rts.eccmp.com/rts/go2.aspx?dl=param"
}
}
AppID -- The App ID from CCMP when an application is registered.
PRID -- The Push Registration ID received from CCMP after the SDK is initialized.
Customer ID -- The Customer ID that gets associated with the PRID. This is supplied by the developer.
Region -- The Region for CCMP.
Token -- The Device Token sent to the device from Firebase. CCMP uses the device token to uniquely identify the device so that Push Notifications can be sent to the device.
The init
method initializes the SDK from the application so that Push Notifications can be received from CCMP. The overloaded method below allows for the region to be specified. If no region is specified, the SDK defaults to North America.
- ctx -- The Application Context for the app using the SDK.
- appIntent -- The Application Intent that was used to start the app using the SDK.
- AppID -- The Application ID from CCMP.
- CustomerID -- The Customer ID that uniquely identifies the user of the applicaiton.
The init
method initializes the SDK from the application so that Push Notifications can be received from CCMP.
- ctx -- The Application Context for the app using the SDK.
- appIntent -- The Application Intent that was used to start the app using the SDK.
- AppID -- The Application ID from CCMP.
- CustomerID -- The Customer ID that uniquely identifies the user of the applicaiton.
- region -- the CCMP region that the application uses.
The RegisterPRIDCallback
method registers a callback in the application which is executed when the PRID has been successfully retrieved from CCMP.
- pridCallback -- a class that implements the SDK's IEMSPRIDCallback interface. The callback expects a method called onPRIDReceived(String prid) that receives a string containing the PRID returned by CCMP for this application/device instance.
The apiPost
method is used to post data from the app to a form hosted in CCMP.
- formId -- the form ID from CCMP for the form you want to post data to
- data -- A key/value structure of the fields and values you want to post to the form
- callback -- A class that implements the IEMSPostCallback::onDataSent(VolleyError error) method. This method is called when the API Post is complete. If the error parameter passed to the method is null, the API Post was successful, otherwise the error will have the data about what exactly went wrong.
The HandleDeepLink
function parses the information from the userActivity and returns the original Deep link URL, the Deep link Paramater if any, and finally register the link count on CCMP.
- intent -- the intent-filter we set up in our manifest to pass the deep link url values
The NotficationOptInStatusCheck()
method is used to confirm Marketing Suite opt-in status for GCM/Firebase notifications to the application.
A call to this method should be placed in the OnResume()
method of the MainActivity class. This will ensure its being called in the case that the user has either turned on or turned off notifications for the application via the Android settings. This will mark the PRID with a status indicating opted-in or opted-out, depending on the setting. Messages from Marketing Suite will only be sent to the device when it is opted-in via the Android settings.
The EMS Mobile SDK is designed to be able to manage inbound push notifications on behalf of the app with minimal intervention. If however the application developer wants to modify the default behavior, the following options are available.
By default, the EMS Mobile SDK will manage the showing of notifications and registering the opens from the push notification by simply adding the following to your Android manifest file.
<receiver android:name="experian.mobilesdk.NotificationReceiver" android:enabled="true">
<intent-filter>
<action android:name="${packageName}.EMS_SHOW_NOTIFICATION" />
<action android:name="${packageName}.EMS_OPEN_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
The EMS Mobile SDK responds to any changes in the Firebase DeviceToken by registering an instance of FirebaseInstanceIdService in the Android Manifest. The application developer can override this functionality by adding the following to their Android.manifest file.
<service
android:name=".IDService">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
The following is the default implementation to handle DeviceToken changes in the EMS Mobile SDK.
package experian.mobilesdk;
import android.util.Log;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
/**
* This is the Firebase ID Services that gets called when a Device Token changes.
*/
public class IDService extends FirebaseInstanceIdService {
private static final String TAG = "IDService";
@Override
public void onTokenRefresh() {
FirebaseInstanceIdService fid = new FirebaseInstanceIdService();
String refreshedToken = FirebaseInstanceId.getInstance().getToken();
Log.d(TAG, "Refreshed token: " + refreshedToken);
try {
EMSMobileSDK.Default().initFromContext(getApplicationContext());
}
catch (Exception e)
{
Log.e(TAG,"Error initializing EMSMobileSDK solely from application context. The SDK must first be initialized with customer mobile application settings");
}
EMSMobileSDK.Default().setToken(getApplicationContext(), refreshedToken);
}
}
NOTE: If you choose to override this default functionality, be sure to call both the
EMSMobileSDK.Default().initFromContext()
, andEMSMobileSDK.Default().setToken()
methods passing in the application context and token received from Firebase respectively, or future notifications will not be received from CCMP.
The EMS Mobile SDK handles data push notifications by registering an instance of FirebaseMessagingService in the Android manifest. If the app developer only wants to be informed of incoming push notifications without changing the default behavior from the SDK, they need only implement a BroadcastReceiver listening for the "com.experian.mobilesdk.EMS_PUSH_RECEIVED" intent.*
<receiver android:name=".MyPushReceiverClass" android:enabled="true">
<intent-filter>
<action android:name="${packageName}.EMS_PUSH_RECEIVED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
public class MyPushReceiverClass extends BroadcastReceiver {
/**
* Received broadcast notifications
* @param context
* @param intent
*/
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(EMSIntents.EMS_PUSH_RECEIVED)) {
// Your Code Here
}
}
}
The EMS Mobile SDK uses the icon defined in the ""\res\drawable\notification_icon.png" of the app. There is a basic icon embedded into the EMS Mobile SDK but the app developer should override this by adding a resource with the same name "notification_icon.png" to their application in the drawable directory.
The EMS Mobile SDK displays basic notification information received from Firebase as part of the default behavior of the FirebaseMessingService instance registered in the Android.manifest file. The app developer can override the notification display process by implementing a listener for the "com.experian.mobilesdk.EMS_SHOW_NOTIFICATION" intent in the Android.manifest file.
<receiver android:name="ShowNotificationReceiver" android:enabled="true">
<intent-filter>
<action android:name="com.experian.mobilesdk.EMS_SHOW_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
The following is the default behavior defined by the SDK in the NotificationReceiver.
public class ShowNotificationReceiver extends BroadcastReceiver {
//ID's used by the notification PI in Android
static final int NOTIFICATION_ID = 109011;
static final String NOTIFICATION_TAG = "EMSNotification";
static final String TAG = "EMS:NotificationReceive";
/**
* Received broadcast notifications
* @param context
* @param intent
*/
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(EMSIntents.EMS_SHOW_NOTIFICATION)) {
Object data = intent.getExtras().get("data");
if (data != null) {
RemoteMessage message = (RemoteMessage) data;
JSONObject jData = new JSONObject(message.getData());
displayNotification(context, jData);
}
}
}
//This method is called whenever a Push Notification comes in.
void displayNotification(Context ctx, JSONObject data){
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ctx);
// set default icon
mBuilder.setSmallIcon(R.drawable.notification_icon);
//Attempts to extract the tile from the Push Notification.
if (data.has("title")){
try {
mBuilder.setContentTitle(data.getString("title"));
} catch (JSONException e) {
mBuilder.setContentTitle("");
}
}
//Attempts to extract the tile from the Push Notification.
if (data.has("body")) try {
mBuilder.setContentText(data.getString("body"));
} catch (JSONException e) {
mBuilder.setContentText("");
}
Intent resultIntent = new Intent(EMSIntents.EMS_OPEN_NOTIFICATION);
try {
resultIntent.putExtra("ems_open",data.getString("ems_open"));
} catch (JSONException e) {
e.printStackTrace();
}
PendingIntent resultPendingIntent = PendingIntent.getBroadcast(ctx, 0, resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
mBuilder.setAutoCancel(true);
NotificationManager mNotifyMgr = (NotificationManager) ctx.getSystemService(NOTIFICATION_SERVICE);
mNotifyMgr.notify(NOTIFICATION_TAG, NOTIFICATION_ID, mBuilder.build());
}
The EMS Mobile SDK handles the response to a user opening the application based on touching a displayed push notification by registering a BroadcastReceiver in the AndroidManifest listening for the "com.experian.mobilesdk.EMS_OPEN_NOTIFICATION" intent. The app developer can override the default behavior by adding the following to the Android.manifest file.
<receiver android:name="OpenNotificationReceiver" android:enabled="true">
<intent-filter>
<action android:name="com.experian.mobilesdk.EMS_OPEN_NOTIFICATION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
The following is the default Receiver implementation used by the SDK for the "com.experian.mobilesdk.EMS_OPEN_NOTIFICATION" intent. Note that it will add the boolean value to the Intent's Extras dictionary for use by your application's onCreate method if needed.
public class OpenNotificationReceiver extends BroadcastReceiver {
/**
* Received broadcast notifications
* @param context
* @param intent
*/
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(EMSIntents.EMS_OPEN_NOTIFICATION)) {
EMSMobileSDK.Default().pushNotificationRegisterOpen(context, intent);
// launch app
try {
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
if (launchIntent == null)
Log.d(TAG, "Unable to find launch intent");
launchIntent.putExtra("EMS_OPEN_FROM_NOTIFICATION", true);
context.startActivity(launchIntent);
Log.d(TAG,"Leaving Receiver: " + launchIntent.getClass().toString());
}
catch (Exception ex)
{
Log.d(TAG, ex.getMessage());
}
}
}
NOTE: If the app developer overrides the default EMS_OPEN_NOTIFICATION intent, you must call EMSMobileSDK.Default().pushNotificationRegisterOpen() method to ensure that the app open gets recorded in CCMP.