Documentation Index

Fetch the complete documentation index at: https://docs.xtremepush.com/llms.txt

Use this file to discover all available pages before exploring further.

Android custom inbox mobile

Prev Next

Implement a custom inbox in your Android application.

By default, the XtremePush SDK renders the inbox as a built-in WebView. A custom inbox replaces that with your own native UI, giving you full control over layout and interaction.

When you implement a custom inbox, the SDK continues to handle:

  • Fetching and paginating inbox messages from the platform

  • Deleting messages

  • Tracking badge counts

  • Sending opened/clicked analytics events (when you call the reporting methods)

Your app becomes responsible for:

  • Rendering each message (title, body, image, icon, card vs alert layout)

  • Handling tap actions (deeplink navigation, opening URLs)

  • Calling the reporting methods at the right time

Setup

  1. Implement the InboxListListener interface in your Application class:

public class XPushApplication extends Application implements InboxListListener {
    @Override
    public void inboxListReceived(ArrayList<InboxMessageListItem> inboxList, WeakReference<Context> uiReference) {
        // render your inbox UI
    }
    @Override
    public void inboxListFailed() {
        // handle error
    }
}
class XPushApplication : Application(), InboxListListener {
    override fun inboxListReceived(inboxList: ArrayList<InboxMessageListItem>, uiReference: WeakReference<Context>) {
        // render your inbox UI
    }
    override fun inboxListFailed() {
        // handle error
    }
}

  1. Register the listener when initialising the SDK. If you don't call setInboxListListener, the SDK uses its built-in WebView inbox.

new PushConnector.Builder(XPUSH_APP_KEY, GOOGLE_PROJECT_NUMBER)
    .setInboxListListener(this)
    .create(this);

Retrieve inbox messages

Call inboxListWithOffset to fetch messages. Results are delivered to the inboxListReceived callback.

mPushConnector.inboxListWithOffset(context, LIMIT, OFFSET);

InboxMessageListItem

Each item in the list has the following fields:

Field

Type

Description

identifier

int

Unique message ID

isOpened

boolean

Whether the message has been marked as opened

isClicked

boolean

Whether the message has been marked as clicked

isDelivered

boolean

Whether the message has been delivered

createTimestamp

Long

Unix timestamp of when the message was created

expirationTimestamp

Long

Unix timestamp of expiry, or null if the message does not expire

style

HashMap<String, String>

Style values — keys: bg (background colour), title_bg (title bar colour)

isCard

boolean

true for card layout (full-width banner image), false for alert layout (small thumbnail)

message

Message

Contains message content and tap action — see below

Working with message content

The message field on each InboxMessageListItem contains the full message content:

Field

Type

Set by

id

String

Platform (system-assigned)

campaignId

String

Platform (system-assigned)

title

String

Campaign — Push title field

text

String

Campaign — Push text / body field

icon

String

Campaign — Push icon field (falls back to app icon, then project icon, if not set)

deeplink

String

Campaign — present when action type is Deeplink; null otherwise

url

String

Campaign — present when action type is URL; null otherwise

data

HashMap<String, String>

Campaign — Custom payload fields (from the data key in the message JSON)

deeplink and url are mutually exclusive — only one will be set depending on the action type configured in the campaign. If neither is set, the message has no tap action.

Layout and style are on the list item:

Field

Type

Set by

isCard

boolean

Campaign — inbox type setting. true = card layout (full-width banner), false = alert layout (small thumbnail)

style.get("bg")

String

Campaign — inbox style background colour

style.get("title_bg")

String

Campaign — inbox style title bar colour

Custom payload fields

If your inbox UI requires data beyond the standard fields — for example a CTA label, a secondary URL, or a badge value — add custom fields in the campaign's Custom payload (payload_add) section. These are delivered in item.message.data.

// Reading a custom payload field
String ctaLabel = item.message.data != null ? item.message.data.get("cta_label") : null;
if (ctaLabel != null) {
    button.setText(ctaLabel);
}
val ctaLabel = item.message.data?.get("cta_label")
ctaLabel?.let { button.text = it }

Campaign Templates

Because your custom inbox UI is built to render a specific content structure, consider defining a reusable inbox campaign template in the Xtremepush platform that consistently populates the fields your UI expects. For example, if your card layout always shows a title, body, background colour, deeplink action, and a custom CTA label, define these as required fields for any inbox campaign targeting your custom implementation.

When a user taps a message, inspect item.message to determine what to do. The SDK does not fire DeeplinkListener callbacks automatically in a custom inbox — your app handles navigation directly.

Always call reportMessageClicked so that the interaction is registered on the platform.

private void onInboxItemTapped(InboxMessageListItem item) {
    // Register the click with the platform
    mPushConnector.reportMessageClicked(item.message, null, null);
    if (item.message.deeplink != null && !item.message.deeplink.isEmpty()) {
        // Route through your app's navigation handler
        // MyRouter.navigate(item.message.deeplink);
    } else if (item.message.url != null && !item.message.url.isEmpty()) {
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(item.message.url));
        context.startActivity(intent);
    } else {
        // No tap action configured — message is informational only
    }
}
private fun onInboxItemTapped(item: InboxMessageListItem) {
    // Register the click with the platform
    mPushConnector.reportMessageClicked(item.message, null, null)
    when {
        !item.message.deeplink.isNullOrEmpty() -> {
            // Route through your app's navigation handler
            // MyRouter.navigate(item.message.deeplink)
        }
        !item.message.url.isNullOrEmpty() -> {
            val intent = Intent(Intent.ACTION_VIEW, Uri.parse(item.message.url))
            startActivity(intent)
        }
        else -> {
            // No tap action configured — message is informational only
        }
    }
}

Report inbox message opened

Call this when a message becomes visible to the user (e.g. scrolled into view in a feed) without a deliberate tap.

mPushConnector.reportMessageOpened(item.message, null, null);
mPushConnector.reportMessageOpened(item.message, null, null)

Report inbox message clicked

Call this when a user deliberately taps a message. This also automatically marks the message as opened. Do not call reportMessageOpened separately for tapped messages.

mPushConnector.reportMessageClicked(item.message, null, null);
mPushConnector.reportMessageClicked(item.message, null, null)

Delete an inbox message

mPushConnector.deleteInboxMessage(String.valueOf(item.identifier), activity);
mPushConnector.deleteInboxMessage(item.identifier.toString(), activity)

Get inbox badge number

Returns the cached unread count — use this to display a badge without making a network request.

int badge = mPushConnector.getInboxBadge();
val badge = mPushConnector.getInboxBadge()