API Reference

Prev Next

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:

  1. Call an SDK method (which returns Call<T>)

  2. Choose how to execute the call

  3. 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 thread

  • enqueue() must be called from the main thread

  • asSuspend() 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: Booleantrue if the SDK is ready, otherwise false

// 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 implementing AppoxeeObserver

  • Returns: 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 String alias

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): true to enable push messaging, false to disable

    • token (String, optional): Firebase device token (if omitted, retrieved automatically)

  • Returns: A Boolean indicating 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 MappMessagingService is 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 DevicePayload object

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 String token, or null if 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 String representing the new Firebase device token

  • Returns: A Booleantrue if the token was updated successfully, false otherwise

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: Current Activity context

    • eventName: 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, or null if no match found

Appoxee.instance().fetchLatestInboxMessage().enqueue(message -> {
    // Use inbox message here
});
val message = Appoxee.instance().fetchLatestInboxMessage().asSuspend()
// Use message here

Get Latest Inbox Message

Fetches the most recent inbox message, if one is available.

  • Input: None

  • Returns: An InboxMessage object, or null if there are no messages

Appoxee.instance().fetchLatestInboxMessage().enqueue(message-> {
   // use inbox message here         
});
val message =Appoxee.instance().fetchLatestInboxMessage().asSuspend()
// use message here

Update 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 not

Geofencing & 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, an ENTER event is triggered immediately.

    • If greater than 0, a DWELL event is triggered instead.

  • Returns: A GeoStatus object 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 GeoStatus object 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: true if active, false otherwise.

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 result

Get 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 attributes

Tags 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 status

Remove 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 attributes

Get 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 attributes

Push 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 of BroadcastReceiver

  • Returns: None

// MyPushBrodacast is subclass of BroadcastRecever
Appoxee.instance().setPushBroadcast(MyPushBroadcast.class);
// MyPushBrodacast is subclass of BroadcastRecever
Appoxee.instance().setPushBroadcast(MyPushBroadcast::class.java)