Overview
This page provides a reference for the public methods available in the Mapp Engage Android SDK v7.
Most public SDK methods return an object of type Call<T> instead of returning a value directly. Understanding this pattern is essential, as nearly all interactions with the SDK are executed through this interface.
A Call<T> represents a deferred request. It allows your application to decide how and when the request should be executed, depending on your threading model and architecture.
This design ensures that:
SDK operations do not block the main thread
Results are returned in a consistent wrapper type (MappResult<T>)
Both Java and Kotlin (coroutines) usage patterns are supported
Important
Each Call<T> instance can be consumed only once. Do not invoke more than one execution method (for example, call both enqueue() and asSuspend() on the same Call instance). Attempting to consume a Call multiple times will throw a CallConsumedException.
If you need to execute the same operation again, request a new Call instance by calling the SDK method again.
In practice, working with the SDK typically follows this pattern:
Call an SDK method (which returns Call<T>)
Choose how to execute the call
Handle the returned MappResult<T>
SDK Call Execution Patterns
The Call<T> interface provides three different ways to execute a request and retrieve an unwrapped result.
Which execution method should you use?
Choose the execution method that matches your application architecture:
enqueue(callback)
Recommended for most Android app flows.
Must be called from the main thread.
Results are delivered asynchronously via callback.
execute()
Intended for Java usage inside a background thread (for example, executors or worker threads).
This call blocks until the result is available and must not be executed on the main thread.
asSuspend()
Intended for Kotlin applications using coroutines.
Can only be called from within a coroutine or another suspending function.
Not supported in Java.
Definition of the Call Interface
interface Call<T> {
/**
* Execute method and get [MappResult]<[T]> result as a return value.
* Should be used from Java code, inside a background executor or thread.
*/
fun execute(): MappResult<T>
/**
* Execute method and get result via callback [MappCallback]<[T]>.
* Should be called from the Main [Thread].
*/
fun enqueue(callback: MappCallback<T>)
/**
* Execute method and get [MappResult]<[T]> as a return value.
* Intended for use in Kotlin applications and works well with coroutines.
*/
suspend fun asSuspend(): MappResult<T>
}Threading Requirements
All examples below must be executed on the appropriate thread:
execute()must be called from a background threadenqueue()must be called from the main threadasSuspend()can only be called from a coroutine or another suspending function
SDK Initialization & Readiness
Is Ready
Check if the SDK has finished initialization and is ready for usage.
Input: none
Returns:
Boolean—trueif the SDK is ready, otherwisefalse
// this method is safe to be called from the Main thread
bool isReady = Appoxee.instance().isReady();
if (isReady) {
// use Engage SDK
}// this method is safe to be called from the Main tread
val isReady = Appoxee.instance().isReady()
if (isReady) {
val alias = result.getData()
}Observe SDK Status
You can observe SDK readiness and registration status by subscribing to an AppoxeeObserver. This is useful if your application needs to react when the SDK becomes ready or handle initialization errors.
Subscribe an Activity or Fragment to SDK initialization changes.
Parameters:
observer— an Activity or Fragment implementingAppoxeeObserverReturns: none
//Implement AppoxeeObserver interface on the activity or fragment.
public class MainActivity extends AppCompatActivity implements AppoxeeObserver{
//...
}
//register activity (or fragment) in some early lifecycle event (e.g. onCreate() or similar)
Appoxee.instance().subscribe(this);
// after that implement methods of a subscribed interface
@Override
public void onReadyStatusChanged(boolean status, @NonNull MappResult<DevicePayload> mappResult) {
// when status is true, SDK is ready to use
// it is safe to call Appoxee.instance().*** methods.
}
// call unsubscribe in the equivalent lifecycle event (e.g. onDestroy() ) to the one where you have registered
Appoxee.instance().unsubscribe(this);//Implement AppoxeeObserver interface on the activity or fragment.
class MainActivity : AppCompatActivity(), AppoxeeObserver{
//...
}
//register activity (or fragment) in some early lifecycle event (e.g. onCreate() or similar)
Appoxee.instance().subscribe(this)
// after that implement methods of a subscribed interface
override fun onReadyStatusChanged(status: Boolean, mappResult: MappResult<DevicePayload>) {
// when status is true, SDK is ready to use
// it is safe to call Appoxee.instance().*** methods.
}
// call unsubscribe in the equivalent lifecycle event (e.g. onDestroy() ) to the one where you have registered
Appoxee.instance().unsubscribe(this)Always unsubscribe observers when they are no longer needed to avoid memory leaks.
User Identity
Set Alias
Assigns a custom alias to a tracked user or device.
Parameters:
alias (String) — Custom alias assigned to the user or device
resendCustomAttributes (boolean) — Indicates whether existing custom attributes should be resent after updating the alias
Returns:
dmcUserId (String)
Call<String> call = Appoxee.instance().setAlias("SOME CUSTOM ALIAS", false);
//call from a main thread
call.enqueue(result -> {
if (result.isSuccess()) {
String dmcUserId = result.getData();
}
});
//call from a background thread
MappResult<String> result = call.execute();
if(result.isSuccess()){
String dmcUserId=result.getData();
}// call from another suspending function or coroutine scope
val call = Appoxee.instance().setAlias("SOME CUSTOM ALIAS", false)
val result = call.asSuspend()
if (result.isSuccess()) {
val dmcUserId = result.getData()
}Get Alias
Retrieves the alias associated with a tracked user or device.
Input: None
Returns: A
Stringalias
Call<String> call = Appoxee.instance().getAlias();
call.enqueue(result -> {
if (result.isSuccess()) {
String alias = result.getData();
}
});
MappResult<String> result = call.execute();
if(result.isSuccess()){
String alias = result.getData();
}val call = Appoxee.instance().getAlias()
val result = call.asSuspend()
if (result.isSuccess()) {
val alias = result.getData()
}Push Messaging
Opt In / Opt Out Device
Sets the device to either an Opt-In or Opt-Out state, enabling or disabling push messaging.
Parameters:
enabled(boolean):trueto enable push messaging,falseto disabletoken(String, optional): Firebase device token (if omitted, retrieved automatically)
Returns: A
Booleanindicating success
Call<Boolean> call = Appoxee.instance().enablePush(true /* or false */, null /* or "FIREBASE DEVICE TOKEN" */);
call.enqueue(result -> {
if (result.isSuccess()) {
Boolean success = result.getData();
}
});
MappResult<Boolean> result = call.execute();
if(result.isSuccess()){
Boolean success = result.getData();
}val call = Appoxee.instance().enablePush(true /* or false */, null /* or "FIREBASE DEVICE TOKEN" */)
val result = call.asSuspend()
if (result.isSuccess()) {
val success = result.getData() ?: false
}Note: This token shouldn't be sent in regular usage. It's mainly for use cases where
MappMessagingServiceis disabled and the client handles Firebase messaging manually.
Check Opt-In Status
Checks whether a device is currently opted in to receive push notifications.
Returns: A
Boolean
Call<Boolean> call = Appoxee.instance().isPushEnabled();
call.enqueue(result -> {
if (result.isSuccess()) {
Boolean enabled = result.getData();
}
});
MappResult<Boolean> result = call.execute();
if(result.isSuccess()){
Boolean enabled = result.getData();
}val call = Appoxee.instance().isPushEnabled()
val result = call.asSuspend()
if (result.isSuccess()) {
val enabled = result.getData() ?: false
}Device Information
Get Device Info
Retrieves information about a registered device.
Input: None
Returns: A
DevicePayloadobject
Call<DevicePayload> call = Appoxee.instance().getDevice();
call.enqueue(result -> {
if (result.isSuccess()) {
DevicePayload payload = result.getData();
}
});
MappResult<DevicePayload> result = call.execute();
if(result.isSuccess()){
DevicePayload payload = result.getData();
}val call = Appoxee.instance().getDevice()
val result = call.asSuspend()
if (result.isSuccess()) {
val devicePayload = result.getData()
}DevicePayload structure:
class DevicePayload(
val dmcUserId: String? = null, // Unique user ID
val udidHashed: String? = null, // Hashed UDID
val pushTokenBk: String? = null, // Opt-Out Token
val pushToken: String? = null, // Opt-In Token
val alias: String? = null // User Alias
)Firebase Token Management
Get Firebase Client Token
Retrieves the Firebase client token for a registered device.
Input: None
Returns: A
Stringtoken, ornullif the device is not registered or opted in
Note: The token will only be available if the device has been successfully registered and is opted in to receive push notifications.
Call<String> call = Appoxee.instance().getFirebaseToken();
//call from a main thread
call.enqueue(result -> {
if (result.isSuccess()) {
String token = result.getData();
}
});
//call from a background thread
MappResult<String> result = call.execute();
if(result.isSuccess()){
String token = result.getData();
}Update Firebase Token
This method should only be used when Mapp's Firebase messaging service is disabled, and a custom Firebase service is implemented in the app.
In such cases, your application must manually provide the Firebase token to the Mapp SDK whenever it changes — typically in the onNewToken() callback.
Input: A
Stringrepresenting the new Firebase device tokenReturns: A
Boolean—trueif the token was updated successfully,falseotherwise
Appoxee.instance().updateFirebaseToken(FB_DEVICE_TOKEN).enqueue(result -> {
if (result.isSuccess()) {
// Token successfully updated
} else {
// Token update failed
}
});val result = Appoxee.instance().updateFirebaseToken(FB_DEVICE_TOKEN).asSuspend()
if (result.isSuccess()) {
// Token successfully updated
} else {
// Token update failed
}In-App Messaging
Fetch In-App Messages
Triggers the retrieval of in-app messages. Messages are displayed automatically by the SDK.
Input:
activity: CurrentActivitycontexteventName: Triggering event (String)
Returns: None
Call<Boolean> call = Appoxee.instance().triggerInApp(requireActivity(), "app_open");
//call from a main thread
call.enqueue(result -> {
if (result.isSuccess()) {
// act based on result
}
});val result = Appoxee.instance().triggerInApp(requireActivity(), "app_open").asSuspend()
if (result.isSuccess()) {
// act based on result
}Inbox Messaging
Fetch Inbox Messages
Fetches inbox messages for the current user.
Input: None
Returns: A
List<InboxMessage>
Appoxee.instance().fetchInboxMessages().enqueue(result -> {
if (result.isSuccess() && result.getData() != null) {
List<InboxMessage> messages = result.getData().getMessages();
// use messages here
} else {
Throwable t = result.getError();
// handle error
}
});// actual call that can be placed from some ViewModel's method
val result = Appoxee.instance().fetchInboxMessages().asSuspend()
if (result.isSuccess()) {
result.getData()?.messages?.let {
// use messages here
}
state.value = InboxStateUI(messages = messages.toImmutableList())
} else {
val error = result.getError()?.message
// handle error
}Get Inbox Message by Template ID
Retrieves the most recent inbox message that matches a given templateId.
Input:
templateId(Int)Returns: An
InboxMessage, ornullif no match found
Appoxee.instance().fetchLatestInboxMessage().enqueue(message -> {
// Use inbox message here
});val message = Appoxee.instance().fetchLatestInboxMessage().asSuspend()
// Use message hereGet Latest Inbox Message
Fetches the most recent inbox message, if one is available.
Input: None
Returns: An
InboxMessageobject, ornullif there are no messages
Appoxee.instance().fetchLatestInboxMessage().enqueue(message-> {
// use inbox message here
});val message =Appoxee.instance().fetchLatestInboxMessage().asSuspend()
// use message hereUpdate Inbox Message Status
Update the status of an inbox message.
Parameters:
message(InboxMessage)messageStatus(MessageStatus)
Returns:
Boolean— update result
Appoxee.instance().updateInboxMessageStatus(message, messageStatus).enqueue(result-> {
// check if result is TRUE or FALSE; if message status was updated or not
});val result = Appoxee.instance().updateInboxMessageStatus(message, messageStatus).asSuspend()
// check if result is TRUE or FALSE; if message status was updated or notGeofencing & Location
Geofencing requirements
Geofencing requires location permissions in your app. Depending on your use case, this may include:
ACCESS_FINE_LOCATION
ACCESS_COARSE_LOCATION
ACCESS_BACKGROUND_LOCATION (required for background geofencing)
Geofencing also requires Google Play Services Location in your project dependencies (com.google.android.gms:play-services-location).
Start Geofencing
Geofencing (also known as geotargeting) is used to trigger engagement actions, such as sending push messages based on the user's physical location.
This feature requires precise location permissions and background location access. For more details, refer to the official Android documentation on geofencing.
Input:
enterDelaySeconds(Integer) — number of seconds to delay the trigger of an enter event.If set to
0, anENTERevent is triggered immediately.If greater than
0, aDWELLevent is triggered instead.
Returns: A
GeoStatusobject indicating whether the method succeeded or failed.
Call<GeoStatus> call = Appoxee.instance().startGeofencing(0);
call.enqueue(result -> {
GeoStatus status = result.getData();
if (status instanceof GeoStatus.GeoStartedOk) {
// Geofencing started successfully
} else if (status instanceof GeoStatus.GeoLocationPermissionsNotGranted) {
// handle location permission not granted
} else {
// handle other errors
}
});val result = Appoxee.instance().startGeofencing<GeoStatus>(0).asSuspend()
result.getData()?.let { geoStatus ->
when (geoStatus) {
is GeoStatus.GeoStartedOk -> { /* Geofencing started */ }
is GeoStatus.GeoLocationPermissionsNotGranted -> { /* Handle permission error */ }
else -> { /* Handle other errors */ }
}
}Stop Geofencing
Stops geofence tracking.
Input: None
Returns: A
GeoStatusobject indicating whether the stop request was successful.
Call<GeoStatus> call = Appoxee.instance().stopGeofencing();
call.enqueue(result -> {
GeoStatus status = result.getData();
if (status instanceof GeoStatus.GeoStoppedOk) {
// Geofencing stopped successfully
} else {
// handle error in stopping geofencing
}
});val result = Appoxee.instance().stopGeofencing<GeoStatus>().asSuspend()
result.getData()?.let { geoStatus ->
if (geoStatus is GeoStatus.GeoStoppedOk) {
// Geofencing stopped successfully
} else {
// Handle error
}
}Check If Geofencing Is Active
Checks whether geofencing is currently active.
Input: None
Returns:
trueif active,falseotherwise.
Appoxee.instance().isGeofencingActive().enqueue(result -> {
if (result.isSuccess()) {
// Geofencing is active
} else {
// Geofencing is not active
}
});
val result = Appoxee.instance().isGeofencingActive().asSuspend()
if (result.isSuccess()) {
// Geofencing is active
} else {
// Geofencing is not active
}Custom Attributes
Add custom attributes
Add custom key-value attributes to a device.
Supported value types: String, Number, Boolean, Date
Parameters:
attributes(Map<String, Any>)Returns:
Boolean— execution result
Call<Boolean> call = Appoxee.instance().addCustomAttributes(Map.of("currency", "EUR", "phone", "+381991234567"))
call.enqueue(result ->
// check if attributes are added
);val result = Appoxee.instance()
.addCustomAttributes(mapOf("currency" to "EUR", "phone" to "+381991234567"))
.asSuspend()
// check resultGet custom attributes
Retrieve custom attributes by key.
Parameters:
attributes(Set<String>)Returns:
Map<String, Any>
Call<Map<String,Object>> call = Appoxee.instance().getCustomAttributes(Set.of("currency","phone"))
call.enqueue(result ->
// use map of the custom attributes
);val result : Map<String,Any?> = Appoxee.instance()
.getCustomAttributes(listOf("currency", "phone"))
.asSuspend()
// use map of the custom attributesTags Management
Add Tags
Add tags to a device.
Parameters:
tags(Set<String>)Returns:
Boolean
Call<Boolean> call = Appoxee.instance().addTags(Set.of("female", "makeup", "fashion"))
call.enqueue(status ->
// check execution status
);val status = Appoxee.instance()
.addTags(setOf("female", "makeup", "fashion"))
.asSuspend()
// check execution statusRemove Tags
Remove tags from a device.
Parameters:
tags(Set<String>)Returns:
Boolean
Call<Boolean> call = Appoxee.instance().removeTags(Set.of("female", "makeup", "fashion"))
call.enqueue(status ->
// check execution status
);val result = Appoxee.instance()
.removeTags(setOf("female", "makeup", "fashion"))
.asSuspend()
// use map of the custom attributesGet Tags
Get cached tags from a device.
Input: none
Returns:
Boolean
Call<Boolean> call = Appoxee.instance().getTags()
call.enqueue(status ->
// check execution status
);val result = Appoxee.instance()
.getTags()
.asSuspend()
// use map of the custom attributesPush Message Handling (Advanced)
Handle Push Message
Handle push messages when using another push provider.
Parameters:
message(RemoteMessage)Returns: none
// it is intended to be used from the extended FirebaseMessagingService
@Override
public void onMessageReceived(@NonNull RemoteMessage message) {
Appoxee.instance().handlePushMessage(message);
}// it is intended to be used from the extended FirebaseMessagingService
override fun onMessageReceived(message: RemoteMessage) {
Appoxee.instance().handlePushMessage(message)
}Check if the Push Message is from Mapp
Check whether a received push message originates from Mapp.
Parameters:
message(RemoteMessage)Returns:
Boolean
// it is intended to be used from the extended FirebaseMessagingService
@Override
public void onMessageReceived(@NonNull RemoteMessage message) {
boolean isMapp= Appoxee.instance().isPushMessageFromMapp(message);
// proceed with the logic and handle push message properly
}// it is intended to be used from the extended FirebaseMessagingService
override fun onMessageReceived(message: RemoteMessage) {
val isMapp = Appoxee.instance().isPushMessageFromMapp(message)
// proceed with the logic and handle push message properly
}Set PushBroadcast
Register a broadcast receiver for push message events.
Parameters:
broadcastReceiverClass— subclass ofBroadcastReceiverReturns: None
// MyPushBrodacast is subclass of BroadcastRecever
Appoxee.instance().setPushBroadcast(MyPushBroadcast.class);// MyPushBrodacast is subclass of BroadcastRecever
Appoxee.instance().setPushBroadcast(MyPushBroadcast::class.java)