Usage
Initializing the Dixa Messenger
Initialize the SDK once, in the onCreate() method of your Application subclass. You need your Messenger token: an admin can find it in the Dixa Dashboard under Settings > Messenger > (your messenger) > Setup.

Call init before any other SDK method, and don't defer it. Application.onCreate() runs before your activities and your Firebase messaging service, so every later call finds the SDK ready. Calls made before init are ignored and logged, with three exceptions: verifyUser is kept and applied when init runs; clearUserCredentials and clearVerificationToken discard a token kept that way; and an unread messages listener is kept and receives count changes once init runs.
Example:
class ApplicationSubclass : Application() {
override fun onCreate() {
super.onCreate()
// Create configuration
val config = DixaMessenger.Configuration.Builder()
.setApiKey("<YOUR_DIXA_MESSENGER_TOKEN>")
.build()
// Initialize DixaMessenger with the configuration
DixaMessenger.init(config, this)
}
}Configuration
The configuration is created with DixaMessenger.Configuration.Builder: chain the options, then call build().
| Builder method | What it sets | Default |
|---|---|---|
setApiKey(String) | Your Messenger token. Required: build() throws an IllegalStateException without it | – |
setPreferredLanguage(String) | The Messenger's language, as a two-letter code. See Language | The device's language |
setLogLevel(LogLevel) | How much the SDK logs. See Log level | LogLevel.ERROR |
setPushNotificationIcon(Int) | A drawable for the push notification's small icon | The Dixa logo |
setUserCredentials(String, String) | A claimed identity at app start. See Authentication | Anonymous |
setVerificationToken(String) | A verified identity at app start. See Authentication | Anonymous |
Example:
val config = DixaMessenger.Configuration.Builder()
.setApiKey("<YOUR_DIXA_MESSENGER_TOKEN>")
.setPreferredLanguage("es")
.setLogLevel(LogLevel.WARNING)
.setPushNotificationIcon(R.drawable.ic_notification)
.build()
DixaMessenger.init(config, this)To change the configuration after init, for example to switch to another Messenger token, pass a new configuration to DixaMessenger.configure(config).
Language
The Messenger uses the languages set in the Dixa Dashboard under Settings > Messenger > (your messenger) > General. Without a preferred language, it uses the device's language if the dashboard supports it, and the dashboard's default language otherwise.

setPreferredLanguage sets the language regardless of the device. Use a two-letter ISO 639-1 code that the dashboard supports; otherwise the Messenger uses the default language.
⚠️ Important Note: Adjusting the language via the SDK will also modify the locale settings of the host application. This is because the SDK utilizes the Locale#setDefault(Locale) and the Configuration#setLocale(Locale) APIs to enforce language changes. Exercise caution, as this may affect the overall behavior and appearance of your application beyond the Dixa Messenger functionality.
Log level
| Level | What's logged |
|---|---|
LogLevel.NONE | Nothing |
LogLevel.ERROR (default) | Critical errors only |
LogLevel.WARNING | Warnings and errors |
LogLevel.ALL | Everything: use it while developing |
Set it with setLogLevel on the Builder, as in the example above. To filter the SDK's logs in Logcat, search for the DixaLog tag.
Authentication
You can decide to have your users identified. The SDK supports three authentication modes:
| Mode | How the user is identified |
|---|---|
| Anonymous (default) | Not identified. No user information is shared with the agent |
| Claimed | A name and email supplied by your app. Users can enter any name and email, so don't rely on it where identity matters |
| Verified | A JSON Web Encryption (JWE) token encrypted with a private key from the Dixa Dashboard |
Choosing the method in the Dixa Dashboard
In the Dixa Dashboard, under Settings > Messenger > (your messenger) > Authentication, Select a method sets how users must be identified before they can start a chat:

| Method in the dashboard | If your app hasn't identified the user |
|---|---|
| Allow anonymous users | Everyone can chat |
| Allow users to claim their identity | The SDK shows a form that asks for a name and email |
| Programmatically authenticate the users | The user can't start a chat |
So identify the user before they open the Messenger.
Claimed
| Method | What it does |
|---|---|
DixaMessenger.updateUserCredentials(name, email) | Stores the user's name and email. Returns a SetCredentialResult |
DixaMessenger.clearUserCredentials() | Removes them, and the user's conversation history on the device |
Example:
when (DixaMessenger.updateUserCredentials("user-name", "email")) {
SetCredentialResult.SUCCESS -> Unit // Stored. A different name or email starts a new session.
SetCredentialResult.FAILURE_ALREADY_CLAIMED -> Unit // The same name and email are already stored.
SetCredentialResult.FAILURE_DOWNGRADE -> Unit // A verification token is stored, so claimed credentials are ignored.
SetCredentialResult.FAILURE_NOT_PROVIDED -> Unit // The name or email was empty.
}Verified
| Method | What it does |
|---|---|
DixaMessenger.verifyUser(token) | Stores the user's JWE token. Returns a SetVerificationTokenResult |
DixaMessenger.clearVerificationToken() | Removes it, and the user's conversation history on the device |
Call verifyUser again with the new token when the token is refreshed: a new token for the same user keeps the user's conversation history.
Example:
when (DixaMessenger.verifyUser("JWE-token")) {
SetVerificationTokenResult.SUCCESS -> Unit // Stored. It is sent when the Messenger connects.
SetVerificationTokenResult.FAILURE_ALREADY_VERIFIED -> Unit // The same token is already stored.
SetVerificationTokenResult.FAILURE_NOT_PROVIDED -> Unit // The token was empty.
}Your backend creates the JWE token, encrypted with a private key from the Dixa Dashboard under Settings > Messenger > (your messenger) > Authentication. The private key is a shared secret, not one half of a key pair: your backend encrypts the token with it and Dixa decrypts it with the same key. See Generating a JWE token for the steps.

Identifying the user at app start
If you already know who the user is when the app starts, you can pass the identity in the configuration instead:
val config = DixaMessenger.Configuration.Builder()
.setApiKey("<YOUR_DIXA_MESSENGER_TOKEN>")
.setUserCredentials("user-name", "email") // Claimed
// or .setVerificationToken("JWE-token") // Verified
.build()Switching users or logging out
On devices shared by several end users, or when one user logs out and another logs in, the SDK keeps the previous identity until you clear it. To hand off to a new user:
- On logout, clear both kinds of identity. Each clear method removes only its own kind, together with the conversation history on the device, so the next user can't read the previous user's conversations.
- When the next user logs in, identify them with
updateUserCredentialsorverifyUser. You don't need to callinitagain.
// On logout from your app
DixaMessenger.clearUserCredentials()
DixaMessenger.clearVerificationToken()Launching the Messenger
Add a button to your app that opens the Messenger.
| Call | Presentation |
|---|---|
DixaMessenger.openMessenger(activity) | A full-screen activity |
DixaMessenger.openMessengerSheet(activity, offsetPx) | A modal bottom sheet (BottomSheetDialogFragment), offsetPx pixels from the top of the screen. The activity must be a FragmentActivity, such as an AppCompatActivity |
Example (full screen):
findViewById<Button>(R.id.buttonOpenMessenger).setOnClickListener {
DixaMessenger.openMessenger(this)
}Example (bottom sheet): the offset leaves room at the top for UI such as a status bar or legal notice. Pass 0 to use the full height.
findViewById<Button>(R.id.buttonOpenMessenger).setOnClickListener {
// Launch with a 100px offset from the top of the screen
DixaMessenger.openMessengerSheet(this, 100)
}Unread messages
Show the user how many unread messages they have, for example as a badge.
| Call | What it does |
|---|---|
DixaMessenger.setUnreadMessagesCountListener(listener) | Calls the listener with the current count straight away, then whenever it changes, including to 0. The SDK keeps one listener: a new one replaces the previous one, and null removes it |
DixaMessenger.getUnreadMessagesCount() | Returns the current count once |
Example:
DixaMessenger.setUnreadMessagesCountListener { amountOfUnreadMessages: Int ->
// Implement logic to display the unread messages count to the user
// For example, updating a notification badge or showing a bubble with the count
}Push notification handling
The Messenger sends push notifications for new messages when your app isn't in use, through Firebase Cloud Messaging (FCM). Your app sets up Firebase, then forwards the FCM token and incoming messages to the SDK.
Setting up Firebase Cloud Messaging
-
Add Firebase to your app: create a Firebase project, register your app and add Firebase Cloud Messaging, as described in Firebase's setup guide. Your app needs the
com.google.firebase:firebase-messagingdependency and itsgoogle-services.jsonfile: the Dixa Messenger SDK doesn't add them to your build. Recent Firebase versions needminSdk24 or higher, so if your app supports API 23, pick a Firebase version that still supports it. -
Create a service account key: in the Firebase Console, go to
Project settings > Service accountsand select Generate new private key. This downloads a JSON file. Keep it safe: it gives access to your Firebase project. -
Add it in the Dixa Dashboard: go to
Settings > Messenger > (your messenger) > Setup > Push notificationsand select Add platform. ChooseFirebase Cloud Messaging, select Choose file to upload the JSON file, then select Submit platform.
-
Add a messaging service: create a class that extends
FirebaseMessagingService, and declare it in your app's manifest. Replace<app-package>and<firebase-service-subclass-name>with your package and class name:<service android:name="<app-package>.<firebase-service-subclass-name>" android:exported="false"> <intent-filter> <action android:name="com.google.firebase.MESSAGING_EVENT" /> </intent-filter> </service>
Asking for permission to show notifications
On Android 13 (API 33) and higher, apps must ask the user for the POST_NOTIFICATIONS permission before they can show notifications. The SDK declares the permission but doesn't ask for it, so your app needs to. Without it, Dixa Messenger notifications aren't shown. See Android's guide on notification runtime permission for when to ask.
Example:
class MainActivity : AppCompatActivity() {
private val notificationPermission =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
// Update your UI if needed
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU &&
checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED
) {
notificationPermission.launch(Manifest.permission.POST_NOTIFICATIONS)
}
}
}Registering the device token
The SDK needs the device's FCM token. Register it in two places:
| Where | Why |
|---|---|
onNewToken in your messaging service | Firebase calls it when the token is created or changes |
At app start, after init | onNewToken doesn't run again for an app that already used Firebase before adding Dixa Messenger, so its token would never be registered |
Example:
class FirebaseMessagingSubclassService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
super.onNewToken(token)
DixaMessenger.PushNotifications.registerNewToken(token)
}
}class ApplicationSubclass : Application() {
override fun onCreate() {
super.onCreate()
DixaMessenger.init(config, this)
FirebaseMessaging.getInstance().token.addOnSuccessListener { token ->
DixaMessenger.PushNotifications.registerNewToken(token)
}
}
}Handling incoming push notifications
Pass every incoming message to the SDK. It shows a notification for Messenger messages and ignores the rest, so your app can handle its own messages as usual.
Example:
class FirebaseMessagingSubclassService : FirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
DixaMessenger.PushNotifications.processNewMessage(remoteMessage)
}
}Push notification API
| Call | What it does |
|---|---|
DixaMessenger.PushNotifications.registerNewToken(token) | Registers the FCM token with the SDK |
DixaMessenger.PushNotifications.processNewMessage(remoteMessage) | Shows a notification if the message is from the Messenger; ignores other messages |