Apps Kit SDK logoApps Kit SDK
Docs · AppsKitSDK (AKS) — Android Integration Guide

9. Local notifications (AppsKitSDKLocalNotificationManager)

AKS ships a small local-notification toolkit — a queue, a notification builder, and an abstract BroadcastReceiver — that you can use to show your own local notifications. AKS does not register the receiver in its manifest or schedule anything for you; both of those are on you.

9.1 Manifest

Subclass AppsKitSDKLocalNotificationBroadCastReceiver (shown in §9.2) and declare your subclass as a <receiver>, merged into the same <application> element from §2:

xml
<application
    android:name=".YourApplication">

    <receiver
        android:name=".YourNotificationReceiver"
        android:exported="false" />

</application>

If you target Android 13+ (API 33), also add the runtime notification permission — AKS's own manifest doesn't declare this, so it won't get merged in for you:

xml
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

POST_NOTIFICATIONS is a runtime permission, so you still need to request it from the user (e.g. via ActivityResultContracts.RequestPermission()) before notifications will actually post.

9.2 Queuing a notification

Subclass AppsKitSDKLocalNotificationBroadCastReceiver and implement checkNotifications() — your hook to decide whether a notification is due, called every time the receiver fires:

kotlin
class YourNotificationReceiver : AppsKitSDKLocalNotificationBroadCastReceiver() {

    override fun checkNotifications() {
        addNotificationInQueue(
            NotificationModel(
                id = "daily_reminder",                      // dedup key — a second add with the same id is ignored
                title = "Come back!",
                description = "You have unfinished items waiting.",
                icon = R.drawable.ic_notification,
                notificationId = 1001,                       // the actual Android notification ID passed to notify()
                targetScreen = "com.yourapp.MainActivity"    // fully-qualified Activity class opened on tap
            )
        )
    }
}

Right after checkNotifications() returns, onReceive automatically calls AppsKitSDKLocalNotificationManager.showNotification(context) — it pops the oldest queued NotificationModel and displays it. You don't call showNotification yourself in this flow; queuing inside checkNotifications() is enough.

This queued-show path checks POST_NOTIFICATIONS itself on Android 13+ and silently skips (logging a line) if it isn't granted, so make sure you've requested it first per §9.1.

9.3 Scheduling

AKS doesn't register or trigger this receiver on any schedule — you decide when onReceive fires, typically with AlarmManager:

kotlin
val intent = Intent(context, YourNotificationReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
    context, 0, intent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)

val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.setRepeating(
    AlarmManager.RTC_WAKEUP,
    System.currentTimeMillis() + intervalMs,
    intervalMs,
    pendingIntent
)

For intervalMs, you can hard-code your own cadence, or honor the value configured in the AKS portal's remote config (HOURS_TO_MAKE_NOTIFICATION, defaults to 2 hours if unset). That value is exposed as getTimeIntervalInMilliSeconds() on the base receiver class, but it's protected, so call it from inside your subclass rather than from the call site above:

kotlin
class YourNotificationReceiver : AppsKitSDKLocalNotificationBroadCastReceiver() {
    fun intervalMillis(): Long = getTimeIntervalInMilliSeconds()
    override fun checkNotifications() { /* ... */ }
}

AlarmManager.setRepeating is inexact under Doze/battery optimizations — if you need it to fire reliably while idle, reschedule with setExactAndAllowWhileIdle on every trigger instead, or move to WorkManager's PeriodicWorkRequest (15-minute minimum interval). AKS doesn't prescribe either; pick whichever fits your app. Also note alarms don't survive a device reboot unless you re-register them yourself (e.g. from a BOOT_COMPLETED receiver).

9.4 Showing a notification directly (no queue)

To post a notification immediately, without going through the queue/receiver flow above:

kotlin
// Tapping opens the Activity at classPath
AppsKitSDKLocalNotificationManager.showNotification(
    context = this,
    id = 2001,
    classPath = "com.yourapp.MainActivity",
    channelId = "general",
    title = "New message",
    message = "You've got a new message waiting.",
    notificationIcon = R.drawable.ic_notification
)

// Or pass a fully-built Intent instead of a class path
AppsKitSDKLocalNotificationManager.showNotification(
    context = this,
    id = 2002,
    intent = Intent(this, MainActivity::class.java).putExtra("from", "notification"),
    channelId = "general",
    title = "New message",
    message = "Tap to view details.",
    notificationIcon = R.drawable.ic_notification
)

Both overloads create the notification channel for you if it doesn't already exist. Unlike the queued path in §9.2, neither checks POST_NOTIFICATIONS itself — request the runtime permission yourself on Android 13+, or the call may silently fail to post.