DEV Community

myougaTheAxo
myougaTheAxo

Posted on • Originally published at zenn.dev

Local Notification Scheduling - WorkManager + Notification Channels

Local Notification Scheduling

NotificationChannel Management

fun createNotificationChannel(context: Context) {
    val channel = NotificationChannel(
        "REMINDER_CHANNEL",
        "Reminders",
        NotificationManager.IMPORTANCE_HIGH
    ).apply {
        description = "Scheduled reminders"
        enableVibration(true)
        setSound(
            RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION),
            AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_NOTIFICATION)
                .build()
        )
    }

    context.getSystemService<NotificationManager>()
        ?.createNotificationChannel(channel)
}
Enter fullscreen mode Exit fullscreen mode

CoroutineWorker Scheduled Notifications

class ReminderWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
    override suspend fun doWork(): Result = withContext(Dispatchers.Default) {
        try {
            val notification = NotificationCompat.Builder(applicationContext, "REMINDER_CHANNEL")
                .setContentTitle("Reminder")
                .setSmallIcon(R.drawable.ic_notification)
                .build()

            NotificationManagerCompat.from(applicationContext)
                .notify(1, notification)

            Result.success()
        } catch (e: Exception) {
            Result.retry()
        }
    }
}

// Schedule:
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
    "reminder",
    ExistingPeriodicWorkPolicy.KEEP,
    PeriodicWorkRequestBuilder<ReminderWorker>(
        15, TimeUnit.MINUTES
    ).build()
)
Enter fullscreen mode Exit fullscreen mode

Action Buttons with BroadcastReceiver

val snoozeIntent = Intent(context, SnoozeReceiver::class.java)
val snoozePendingIntent = PendingIntent.getBroadcast(
    context, 0, snoozeIntent,
    PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)

val notification = NotificationCompat.Builder(context, "REMINDER_CHANNEL")
    .setContentTitle("Reminder")
    .addAction(R.drawable.ic_snooze, "Snooze", snoozePendingIntent)
    .build()
Enter fullscreen mode Exit fullscreen mode

Compose Reminder Settings UI

@Composable
fun ReminderSettingsScreen() {
    var reminderTime by remember { mutableStateOf(9 * 60) } // 9:00 AM
    var isEnabled by remember { mutableStateOf(true) }

    Column(modifier = Modifier.padding(16.dp)) {
        Switch(
            checked = isEnabled,
            onCheckedChange = { isEnabled = it }
        )

        if (isEnabled) {
            TimePicker(
                time = reminderTime,
                onTimeChange = { reminderTime = it }
            )
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

8 Android app templates on Gumroad

Top comments (0)