Resources
The latest Android SDK version is 3.7.11.
What is the Emarsys SDK?
The Emarsys SDK enables you to use Mobile Engage in a very straightforward way. By incorporating the SDK in your app, we support you, among other things, in handling credentials, API calls, tracking of opens and events as well as logins and logouts in the app.
The Emarsys SDK is open sourced to enhance transparency and to remove privacy concerns. This also means that you can always be up-to-date with what we are working on.
Using the SDK is also beneficial from the product aspect: it simply makes it much easier to send push messages through your app. You do not have to follow and implement changes in our API calls, endpoints and parameters: we do it for you in the SDK. Your only task is to use the latest version of the SDK in your app and we take care of everything else.
Capture explicit consent for data tracking and collection
Before you use Android SDK you must make sure to capture explicit consent before tracking and collecting data.
It is your responsibility to ensure that you always obtain the necessary consent for that data from your consumers (i.e: a natural person such as a customer, contact, or account). You will find further details on what is automatically tracked by the Emarsys SDK's and what can be manually tracked here.
Android SDK Installation
Video Tutorial
In the video below, an Emarsys Mobile Engineer walks through the standard installation of the Emarsys Android SDK on a mobile app.
1. Requirements
The minimum Android version should be at least API level 24 and the compileSdkVersion 31 or higher. The Emarsys SDK uses AndroidX namespace libraries and therefore AndroidX should also be supported.
To integrate Firebase into your app, follow the instructions in the Firebase documentation. Please note, however, that you do not need to add Firebase dependencies for firebase-core
and firebase-messaging
, because they are already included in the Emarsys SDK.
Emarsys App code, which is generated when the app is added to the account.
Emarsys Predict Merchant ID (If the Predict feature is enabled on the Emarsys account).
Wherever you see <String> or anything similar in <> brackets, you should change those according to your own naming convention.
2. Dependencies
Emarsys SDK 3.0.0 requires Java 1.8 to use and the upgraded Kotlin runtime to the latest version 1.5.x.
Add the following code to your build.grade, if your application does not use Java 1.8 or Kotlin:
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8
}
3. Specifying the Emarsys SDK
To integrate the Mobile Engage SDK into your Android project using Gradle, you have to specify it in your application's build.gradle
file:
...
dependencies {
implementation 'com.emarsys:emarsys-sdk:<VERSION>'
}
...
To find out the latest version release of the Emarsys SDK, please refer to Android Emarsys SDK Github page here.
4. Set Push Token and Track Message Opens
4.1. Custom notification icon
You can set a custom notification icon, by specifying it as a meta-data between your application tag:
<meta-data
android:name="com.emarsys.mobileengage.small_notification_icon"
android:resource="@drawable/notification_icon" />
4.2. Push notifications: Firebase, Huawei
4.3. Integrating Firebase push notification
When the pushToken arrives we need to set it using Emarsys.Push.setPushToken()
. For more information about how to obtain your FCM token, consult the Firebase integration guides:
The recommended way of using the SDK is to enable the Emarsys SDK to automatically handle setPushToken
and trackMessageOpen
calls for you:
Add emarsys-firebase
into your app build gradle:
...
dependencies {
implementation 'com.emarsys:emarsys-firebase:<latest-version>'
}
...
Register this service in your manifest:
<service android:name="com.emarsys.service.EmarsysFirebaseMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
4.3.1. Adding custom implementation to Firebase push
You can add your custom implementation to handle setPushToken
and trackMessageOpen
.
Use this approach to handle multiple push providers.
Java
public class MyMessagingService extends FirebaseMessagingService {
@Override
public void onNewToken(String token) {
super.onNewToken(token);
Emarsys.Push.setPushToken(token);
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
boolean handledByEmarsysSDK = EmarsysFirebaseMessagingServiceUtils.handleMessage(this, remoteMessage);
if (!handledByEmarsysSDK) {
//handle your custom push message here
...
}
}
}
Kotlin
class MyMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String?) {
super.onNewToken(token)
Emarsys.Push.setPushToken(token!!)
}
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
val handledByEmarsysSDK =
EmarsysFirebaseMessagingServiceUtils.handleMessage(this, remoteMessage)
if (!handledByEmarsysSDK) {
//handle your custom push message here
...
}
}
}
4.4. Integrating Huawei push notification
Push sending for Huawei is unavailable for devices below API level 22!
Huawei Push Messaging is only available from Emarsys SDK 3.0.0!
Emarsys SDK checks if the device has Google Play Services available and if not, it is considered as a Huawei device. Please note that as Google Play Services is not available with Huawei only integrations, Geofencing will not work!
Set the Huawei Push token using Emarsys.Push.setPushToken()
. For more information about how to obtain your HMS token please consult the Huawei integration guides:
The recommended way of using the SDK is to enable the Emarsys SDK to automatically handle setPushToken
and trackMessageOpen
calls for you:
Add emarsys-huawei
into your app build gradle:
...
dependencies {
implementation 'com.emarsys:emarsys-huawei:<VERSION>'
}
...
Register this service in your manifest:
<meta-data
android:name="com.huawei.hms.client.channel.androidMarket"
android:value="false" />
<meta-data
android:name="push_kit_auto_init_enabled"
android:value="true" />
<service
android:name="com.emarsys.service.EmarsysHuaweiMessagingService"
android:exported="false">
<intent-filter>
<action android:name="com.huawei.push.action.MESSAGING_EVENT"/>
</intent-filter>
</service>
4.4.1. Adding custom implementation to Huawei push
Use this approach to handle multiple push providers.
You can add your custom implementation to handle setPushToken
and trackMessageOpen
.
Java
public class MyMessagingService extends HmsMessageService {
@Override
public void onNewToken(String token) {
super.onNewToken(token);
Emarsys.Push.setPushToken(token);
}
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
super.onMessageReceived(remoteMessage);
boolean handledByEmarsysSDK = EmarsysHuaweiMessagingServiceUtils.handleMessage(this, remoteMessage);
if (!handledByEmarsysSDK) {
//handle your custom push message here
...
}
}
}
Kotlin
class MyMessagingService : HmsMessageService() {
override fun onNewToken(token: String?) {
super.onNewToken(token)
Emarsys.Push.setPushToken(token!!)
}
override fun onMessageReceived(remoteMessage: RemoteMessage?) {
super.onMessageReceived(remoteMessage)
val handledByEmarsysSDK =
EmarsysHuaweiMessagingServiceUtils.handleMessage(this, remoteMessage)
if (!handledByEmarsysSDK) {
//handle your custom push message here
...
}
}
}
5. Initialization
To configure the SDK, you should execute the following in the onCreate
method in the Application
class.
applicationCode: is needed if you want to use Mobile Engage features
merchantId: is needed if you want to use Predict features
inAppEventHandler: is needed if you want to handle user actions on the inApp messages
notificationEventHandler: is needed if you want to handle user actions on the push messages
silentMessageEventHandler: is needed if you want to handle silent messages
onEventActionHandler: is needed if you want to handle onEventActions
Java
public class SampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
EmarsysConfig config = new EmarsysConfig.Builder()
.application(this)
.applicationCode(<applicationCode:String?>)
.merchantId(<merchantId:String?>)
.build();
Emarsys.setup(config);
}
}
Kotlin
class SampleApplication : Application() {
override fun onCreate() {
super.onCreate()
val config = EmarsysConfig(application=this,
applicationCode=<applicationCode:String?>,
merchantId=<merchantId:String?>)
Emarsys.setup(config)
}
}
The applicationCode
, and predictMerchantId
are generated from the Emarsys account.
5.1. CompletionListener
Most calls can receive a completionListener
as parameter, that you can use to track the calls. The CompletionListener
defines one method:
Java
@Override
public void onCompleted(@Nullable Throwable errorCause) {
if(errorCause != null){
Log.e(TAG, error.getMessage(), error);
}
}
6. Contact Management
The setContactFieldId
should not be set to 3 (email). In order to prevent your customers' personal data (PII) being stored in our cloud infrastructure, we require use of unique, non-guessable and immutable contact identifiers. Customer ID's are considered secure. Salted email hash is no longer supported for new Mobile Engage implementations. To make sure the behavioural tracking is cross devices (i.e. mobile and web), the Web Extend contact ID should also use Customer ID and match that used on mobile.
6.1. Identifying Contacts
When the application setup is finished, you can use the setContact
method to identify the user. The CompletionListener
is optional.
The setContact
call only has to be placed once to connect the device to the contact record in Emarsys. It does not need to be placed for every time the app starts. However, if the contact has been logged out using the clearContact
method, the setContact
call should be placed the next time the contact logs into the account to reconnect the device with the contact record.
Java
Emarsys.setContact(Integer contactFieldID, String contactFieldValue,CompletionListener completionListener);
Kotlin
Emarsys.setContact(contactFieldID: Int, contactFieldValue: String, completionListener: CompletionListener? = null)
6.2. Clear contact
Use the clearContact
method to remove the device details from the contact record, for example, if the user signs out of the app, and they should not receive personalised messages. The CompletionListener
is optional.
Java
Emarsys.clearContact(CompletionListener completionListener);
Kotlin
Emarsys.clearContact(completionListener: CompletionListener? = null)
With the device details removed from the contact record, the user is still reachable for mobile marketing using the anonymous contact record.
6.3. Clear push token
Use the clearPushToken
method to remove the push token of the contact. The CompletionListener
parameter is optional.
Java
Emarsys.getPush().clearPushToken(CompletionListener completionListener);
Kotlin
Emarsys.push.clearPushToken(completionListener: CompletionListener? = null)
7. Predict Event Tracking
Events are a powerful tool to allow marketers to automate user journeys. Therefore, implementing events on any key user milestone within the app mitigates the need for future ad-hoc development requests to satisfy new marketing contact journeys.
7.1. Track Predict Cart Events
When a contact adds items to the cart, the contents of the cart can be tracked by using the trackCart
method.
Java
Emarsys.getPredict().trackCart(List<CartItem> items);
Kotlin
Emarsys.predict.trackCart(items: List<CartItem>)
7.2. Track Predict Purchase Events
When a contact makes a purchase, the purchase can be tracked by using the trackPurchase
method. It is required to include the orderId
parameter when calling this method.
Java
Emarsys.getPredict().trackPurchase(String orderId, List<CartItem> items);
Kotlin
Emarsys.predict.trackPurchase(orderId: String, items: List<CartItem>)
7.3. Track Predict Item Views
When a contact views an item, the view can be tracked by using the trackItemView
method. It is required to include the itemId
parameter when calling this method.
Java
Emarsys.getPredict().trackItemView(String itemId);
Kotlin
Emarsys.predict.trackItemView(itemId: String)
7.4. Track Predict Category Views
When a contact views a category, the category view can be tracked by using the trackCategoryView
method.
Java
Emarsys.getPredict().trackCategoryView(String categoryPath)
Kotlin
Emarsys.predict.trackCategoryView(categoryPath: String)
The categoryPath
is required to exactly match that of the product catalogue
7.5. Track Predict Search Term
When a contact enters a search term, the search term can be tracked by using the trackSearchTerm
method.
Java
Emarsys.getPredict().trackSearchTerm(String searchTerm)
Kotlin
Emarsys.predict.trackSearchTerm(searchTerm: String)
7.6. Track Predict Custom Tag
Use the trackTag
method to track custom tags. The eventName
parameter is required, though the attributes are optional.
Java
Emarsys.getPredict().trackTag(String eventName, Map<String,String> attributes);
Kotlin
Emarsys.predict.trackTag(eventName: String, attributes: Map<String,String>?)
8. Tracking Custom Events
Custom events cannot be deleted and therefore should not contain any PII data
Use the trackCustomEvent
method to track custom events. When implementing, the eventName
parameter is required, though the attributes and the CompletionListener are optional.
With Emarsys SDK 3.0.0 we made every callback we use a Functional Interface so you can use them as lambda functions from both Java 8 and Kotlin.
Java
Emarsys.trackCustomEvent(String eventName, Map<String,String> attributes, CompletionListener completionListener);
Kotlin
Before:
Emarsys.trackCustomEvent(eventName, attributes, CompletionListener(){
@Override
public void onCompleted(Throwable throwable){
}
});
After
Emarsys.trackCustomEvent(eventName, attributes,(throwable)->{});
This also means that all Kotlin lambda-based methods have been removed from our API since Functional Interfaces can be used as Kotlin lambda out of the box.
9. In-app
9.1. Pause In-app campaigns
When a critical contact activity starts, use pause to stop any disruptions in the user journey by pausing In-app messages. The most common utilisation of the pause
method is on the payment wall.
Java
Emarsys.getInApp().pause();
Kotlin
Emarsys.inApp.pause()
When you issue the pause
command, triggers for In-app messages get ignored. If you want them to be delivered, they must be resent after the resume
command is given.
9.2. Resume In-app campaigns
When the contact is no longer engaging with a critical activity, and In-app messages should resume after a pause, use the resume
method.
Java
Emarsys.getInApp().resume();
Kotlin
Emarsys.inApp.resume()
9.3. React to In-app message triggered event
To react to an event triggered by the In-app message, you can register for it using the setEventHandler
method. The eventHandler
is a callback for an In-app message event.
Java
Emarsys.getInApp().setEventHandler(EventHandler() {
@Override
public void handleEvent(String eventName, @Nullable JSONObject payload) {
...
}
});
Kotlin
Emarsys.inApp.setEventHandler { eventName, payload -> ...}
9.4. Inline In-app
In-app message, that takes place in the application's view hierarchy. Multiple inline In-app components are allowed in one screen.
9.4.1. Implementing Inline In-app
There are three ways to implement the inline In-app.
- First option is from XML, this way onAppEventListener, onCompletionListener and onCloseListener cannot be set.
- Secondly is completely from code, this way it could be set up by its constructor.
- The last one is the mixed setup, for this the view could be created in XML, then the listeners should be set by code.
9.4.2. Loading Inline In-app
In order to load the inline In-app, the loadInApp
must be called with the corresponding viewId
. When the view is created from XML and this value has been set, this call is unnecessary.
Java
InlineInAppView inlineInAppView = new InlineInappView(Context context);
inlineInAppView.loadInApp(String viewId);
Kotlin
val inlineInAppView = InlineInAppView(context: Context)
inlineInAppView.loadInApp(viewId: String)
9.4.3. React to Inline In-app event
In order to react to an event triggered from the In-app message, register an onAppEventListener
. The onAppEventListener
is a callback for an In-app message event.
Java
inlineInAppView.setOnAppEventListener((<String property>, <JSONObject jsonObject>) -> {
...
});
Kotlin
inlineInApp.onAppEventListener = { property: String?, json: jsonObject ->
...
}
9.4.4. Inline on completion listener
The onCompletionListener
is triggered when the inline In-app message is loaded.
Java
inlineInAppView.setOnCompletionListener(<Throwable errorCause> -> {
...
});
Kotlin
inlineInApp.onCompletionListener = CompletionListener { throwable: Throwable? ->
...
}
9.4.5. Inline on close listener
The onCloseListener
is triggered when the close button has been clicked on the inline In-app message.
Java
inlineInAppView.setOnCloseListener(() -> {
...
});
Kotlin
inlineInApp.onCloseListener = {
...
}
10. Switch applicationCode, merchantId and contactFieldId
To allow for the switching of accounts, the Emarsys SDK now includes functions to either set, switch or remove the application code, merchant ID (use for Predict tracking and recommendations) and the contact field ID. The functions do not require a session restart, and common use case would include switching between Emarsys accounts.
10.1. Change Application Code
With the Emarsys SDK 3.0.0 we simplified changeApplicationCode
by removing the methods with the contactFieldId
. contactFieldId
is now part of setContact
.
The SDK should be initialized with the new application code when the app starts the next time.
The SDK will call clearPushToken
and clearContact
for the old application code automatically. You should call setPushToken
and setContact
when necessary for the new application code in the completion listener.
Java
Emarsys.getConfig().changeApplicationCode(applicationCode, (CompletionListener) errorCause -> {
if (errorCause == null) {
Emarsys.getPush().setPushToken(pushToken);
if (contactIsLoggedIn) {
Emarsys.setContact(contactFieldID, contactFieldValue);
}
}
});
Kotlin
Emarsys.config.changeApplicationCode(applicationCode) { error ->
if (error == null) {
Emarsys.push.setPushToken(pushToken)
if (contactIsLoggedIn) {
Emarsys.setContact(contactFieldID, contactFieldValue)
}
}
}
10.2. Change Predict Merchant ID
Java
Emarsys.getConfig().changeMerchantId(String merchantId);
Kotlin
Emarsys.config.changeMerchantId(merchantId: String?)
11. Retrieve Device Settings
The Emarsys config function allows the retrieval of current SDK configuration. This includes:
- Application Code
- Merchant ID
- Contact ID
- Hardware ID
- Language
- Notification Settings
11.1. Get Application Code
Java
Emarsys.getConfig().getApplicationCode();
Kotlin
Emarsys.config.applicationCode
11.2. Get Merchant ID
Java
Emarsys.getConfig().getMerchantId();
Kotlin
Emarsys.config.merchantId
11.3. Get Contact Field ID
Java
Emarsys.getConfig().getContactFieldId();
Kotlin
Emarsys.config.contactFieldId
11.4. Get Hardware ID
Java
Emarsys.getConfig().getHardwareId();
Kotlin
Emarsys.config.hardwareId
11.5. Get LanguageCode
Java
Emarsys.getConfig().getLanguageCode();
Kotlin
Emarsys.config.languageCode
11.6. Get Notification Settings
Java
Emarsys.getConfig().getNotificationSettings();
Kotlin
Emarsys.config.notificationSettings
12. Inbox Notifications
Emarsys only provides the payload with the messages. The customer’s development team is responsible for building the inbox UI. For more information on Inbox payloads, see Payload examples.
12.1. Fetch Messages
To retrieve the Inbox messages for a contact, use the fetchMessages
method.
Java
Emarsys.getMessageInbox().fetchMessages(result -> {
if (result.getResult() != null) {
InboxResult inboxResult = result.getResult();
Log.i(TAG, "Inbox result: " + inboxResult.toString());
}
if (result.getErrorCause() != null) {
Throwable cause = result.getErrorCause();
Log.e(TAG, "Error happened: " + cause.getMessage());
}
});
Kotlin
Emarsys.messageInbox.fetchMessages {
it.result?.let { notificationStatus ->
notificationStatus.messages.forEach { notification ->
Log.i(TAG, "Messages: ${notification.title}")
}
}
it.errorCause?.let { cause ->
Log.e("Error fetching messages: ${cause.message}")
}
}
12.2. Message Tag
Tags are to be used to set the status of the inbox message, e.g. opened, seen etc. There are 6 tags in total and the details are confirmed in the table below. App developers can add the tags seen, opened, pinned and deleted. It is important to note all the tags though as they will be included in the message payload in the SDK Tag field. Depending on the tag included in the message, the message could be handled differently by the app. An example would be that messages tagged with "high" (for High Priority) could be visible flagged/highlighted by the contact.
Only the tags specified below are supported. Any custom tags created will not work.
Tag Name | Tag | Description | Where it can be added |
---|---|---|---|
High Priority |
high | Marketer setting of high priority message You can activate this tag from your inbox-campaign by ticking the relevant checkbox. Your developers have to graphically represent this setting in the app inbox. |
Emarsys UI |
Cancelled |
cancelled |
Marketer cancelled the message This tag is automatically added to your inbox campaign when you recall it. |
Emarsys UI |
Seen |
seen |
Inbox messages visible in the app inbox but not opened |
Mobile App via the SDK |
Opened |
opened |
Messages opened on the app |
Mobile App via the SDK |
Pinned |
pinned |
Messages that are pinned as favourite by the contact |
Mobile App via the SDK |
Deleted |
deleted |
Messages that are deleted in the app UI |
Both Emarsys UI and/or Mobile App via the SDK |
12.2.1. Add Message Tag
To add a message tag, use the addTag
method.
Java
Emarsys.getMessageInbox().addTag(String tag, String messageId, CompletionListener completionListener);
Kotlin
Emarsys.messageInbox.addTag(tag: String, message: String, completionListener: CompletionListener? = null);
12.2.2. Remove Message Tag
To remove a message tag, use the removeTag
method.
Java
Emarsys.getMessageInbox().removeTag(String tag, String messageId, CompletionListener completionListener? = null);
Kotlin
Emarsys.messageInbox.removeTag(tag: String, message: String, completionListener: CompletionListener);
Verifying the SDK
You can check whether the SDK calls have been received by our servers by clicking the SDK events icon on the Apps tab of the Mobile Engage user interface.
The Name column shows the event that has been received, while the Status column shows the response code. If this value is 201 or 202, then the integration of your SDK has been successful.
Frequently Asked Questions
SDK updates
Each new release of the SDK brings either new features or fixes known issues, so it is always beneficial to update to the newest version.
We are working hard to ensure the SDK is of the highest quality, and this includes taking backwards compatibility very seriously.
In general, you should update your version as often as you can. Even if you are not planning to incorporate new features into your app, we still encourage you to at least update when a new patch version comes out, so you will not miss the bug fixes and other enhancements in the SDK.
The SDK versioning follows the x.y.z pattern, where x is the major version, y is the minor version and z is the patch version.
- Major version - This brings a significant release online, such as a long-awaited new feature. Although it is against our intentions, it may happen that a new major version may affect backwards compatibility with the previous release. We strive to keep this to a minimum and do so only with a solid reason for it. This will always be duly communicated beforehand.
- Minor version - This brings smaller new features. Minor versions never break backwards compatibility.
- Patch version - This brings bugfixes, stability and performance enhancements. Patch versions never break backwards compatibility, either.
The main purpose of the default FCM services in the SDK is to provide an implementation that works for you out-of-the-box when integrating the SDK. We try to keep the services generic, so that they suite the default use cases of our customers. If you have special requirements, we recommend implementing your own Firebase services, based on our default implementation.
When implementing your own FCM service, make sure to handle messageOpens
correctly.
The issue is not on our side, it comes from the Firebase service. For more information, consult the Firebase documentation.
If your organisation has a firewall that restricts the traffic to or from the Internet, you need to configure it to allow connectivity with FCM in order for your Firebase Cloud Messaging client apps to receive messages. The ports to open are: 5228, 5229, and 5230. FCM typically only uses 5228, but it sometimes uses 5229 and 5230. FCM doesn't provide specific IPs, so you should allow your firewall to accept outgoing connections to all IP addresses contained in the IP blocks listed in Google's ASN of 15169. For more information, check Google Cloud Messaging service's documentation.
To resolve this, please check the following:
- Have you downloaded the google-services. json? If not, please consult the Firebase documentation to setup your app with firebase first.
- Make sure your connection to Firebase is not limited by company firewall rules.
- Make sure you see push tokens in your SDK logs in the Mobile Engage user interface.
Make sure you have registered our services (EmarsysMessagingService
) in your AndroidManifest.xml
.
Make sure you have registered our services (EmarsysMessagingService
) in your AndroidManifest.xml
.