Skip to content

Badges

Pulsate supports two kinds of unread indicators:

  • App-icon badges — the dot/number on your launcher icon, driven by Android’s native notification badge mechanism.
  • In-app badges — unread counts you render inside your own UI (e.g. on an “Inbox” button).

The SDK sets the badge count with NotificationCompat.setNumber() — the native Android API. Depending on the device and launcher this shows as a number, a dot, or nothing at all.

Badge visibility is a property of the SDK’s notification channel, controlled by PulsateConfig.NOTIFICATION_CHANNEL_SHOW_BADGES (default true). Set it in Application.onCreate() before the first notification:

override fun onCreate() {
super.onCreate()
PulsateConfig.NOTIFICATION_CHANNEL_SHOW_BADGES = false
}

For launchers that don’t honor the native API, combine the badge listener below with a third-party library such as ShortcutBadger.

Option 1 — setBadgeUpdateListener (real-time)

Section titled “Option 1 — setBadgeUpdateListener (real-time)”

The SDK pushes badge updates to your listener on three events: leaving the Pulsate Inbox, session start, and receiving a push. Your callback can also modify the count by returning a different value:

class MyApp : Application() {
override fun onCreate() {
super.onCreate()
val pulsateManager = PulsateFactory.getInstance()
pulsateManager.setBadgeUpdateListener(object : IPulsateBadgeUpdateListener {
override fun onBadgeUpdate(badge: Int): Int {
ShortcutBadger.applyCount(this@MyApp, badge)
return badge // return the (possibly adjusted) count the SDK should use
}
})
}
}

Feeding the count into UI state via a ViewModel:

class MenuViewModel : ViewModel() {
private val _badgeState = MutableLiveData(0)
val badgeState: LiveData<Int> get() = _badgeState
init {
PulsateFactory.getInstance().setBadgeUpdateListener(
object : IPulsateBadgeUpdateListener {
override fun onBadgeUpdate(badge: Int): Int {
_badgeState.postValue(badge)
return badge
}
},
)
}
}
class MenuFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
menuViewModel.badgeState.observe(viewLifecycleOwner) { badge ->
binding.inboxBtn.text = "INBOX $badge"
}
}
}

Option 2 — getFeedUnreadCount (on demand)

Section titled “Option 2 — getFeedUnreadCount (on demand)”

Query the unread count directly — for example after the user closes the Feed (onFeedClose) or after session start:

private fun updateBadge() {
PulsateFactory.getInstance().getFeedUnreadCount(
object : IPulsateValueListener<Int> {
override fun onSuccess(value: Int) {
binding.feedBtn.text = "Inbox ($value)"
}
override fun onError(e: Throwable) {
e.printStackTrace()
}
},
)
}
// Refresh when the user closes the Feed:
binding.feedBtn.setOnClickListener {
PulsateFactory.getInstance().showFeed(object : IPulsateFeedListener {
override fun onFeedClose() = updateBadge()
})
}