Skip to main content

Android Events

The Lovina Chat SDK emits events through the onEvent callback on LovinaChatWidget. Use these events to react to chat activity in your native code.

Event Listener Pattern

Set the onEvent callback before or after calling configure():

chatWidget.onEvent = { event ->
when (event) {
is ChatEvent.Loaded -> { /* ... */ }
is ChatEvent.MessageReceived -> { /* ... */ }
is ChatEvent.UnreadCountChanged -> { /* ... */ }
is ChatEvent.Closed -> { /* ... */ }
is ChatEvent.Error -> { /* ... */ }
}
}

ChatEvent Types

ChatEvent.Loaded

Emitted when the widget has finished loading and is ready for interaction.

PropertyTypeDescription
authTokenString?Session auth token, if the user has an active session.
is ChatEvent.Loaded -> {
Log.d("Chat", "Widget loaded, token: ${event.authToken}")
}

ChatEvent.MessageReceived

Emitted when a new message is received (from an agent or bot).

PropertyTypeDescription
messageMap<String, Any?>Full message payload including content, sender, attachments, etc.
is ChatEvent.MessageReceived -> {
val content = event.message["content"] as? String
val sender = (event.message["sender"] as? Map<*, *>)?.get("name")
Log.d("Chat", "Message from $sender: $content")
}

ChatEvent.UnreadCountChanged

Emitted when the number of unread messages changes. Useful for updating notification badges.

PropertyTypeDescription
countIntCurrent number of unread messages.
is ChatEvent.UnreadCountChanged -> {
updateBadge(event.count)
}

ChatEvent.Closed

Emitted when the chat is closed, either by the user or the agent.

PropertyTypeDescription
reasonString?Optional reason for closure (e.g., "user", "resolved").
is ChatEvent.Closed -> {
Log.d("Chat", "Chat closed: ${event.reason}")
finish()
}

ChatEvent.Error

Emitted when an error occurs within the widget.

PropertyTypeDescription
codeStringError code (e.g., "network_error", "auth_failed").
messageStringHuman-readable error description.
is ChatEvent.Error -> {
Log.e("Chat", "Error [${event.code}]: ${event.message}")
showErrorToast(event.message)
}

Full Example

chatWidget.onEvent = { event ->
when (event) {
is ChatEvent.Loaded -> {
Log.d("Chat", "Ready")
}
is ChatEvent.MessageReceived -> {
val content = event.message["content"] as? String ?: ""
showNotification("New message", content)
}
is ChatEvent.UnreadCountChanged -> {
badgeView.text = if (event.count > 0) "${event.count}" else ""
badgeView.isVisible = event.count > 0
}
is ChatEvent.Closed -> {
finish()
}
is ChatEvent.Error -> {
Toast.makeText(this, event.message, Toast.LENGTH_SHORT).show()
}
}
}

Common Patterns

// In your main Activity — open chat as a new Activity
startActivity(Intent(this, ChatActivity::class.java))

// In ChatActivity
class ChatActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val widget = LovinaChatWidget(this)
widget.onEvent = { event ->
if (event is ChatEvent.Closed) {
finish() // goes back to previous Activity
}
}
widget.configure(config)
setContentView(widget)
}
}

Fragment: Pop on close

widget.onEvent = { event ->
if (event is ChatEvent.Closed) {
parentFragmentManager.popBackStack()
}
}

Show unread badge

is ChatEvent.UnreadCountChanged -> {
val badge = bottomNav.getOrCreateBadge(R.id.chat_tab)
badge.isVisible = event.count > 0
badge.number = event.count
}