Skip to content Skip to sidebar Skip to footer

Send Daily Notification At A Scheduled Time Android

I am trying to send notification daily at 10am. The code works fine when app is running and in background, but it does not work when the app is terminated/Killed. Here is what I am

Solution 1:

Monday, August 30, 2021

According to official documents, you can use alarmMgr.setInexactRepeating() but due to the system being busy it does not work properly I found another way to do this work. Use alarmMgr.set() for this purpose this will Wake up the device to fire a one-time (non-repeating) alarm. But when it triggers the device give it next date and time. It works properly when the app is terminated/Killedwork I am describing both methods just follow which one you want

SourceCode

Method 1

NotificationUtils.kt

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat

classNotificationUtils(context:Context) {

    privatevar mContext = context
    privatelateinitvar notificationBuilder: NotificationCompat.Builder
    val notificationManager = NotificationManagerCompat.from(mContext)
    privateval CHANNEL_ID = "My_Notification_Channel"init {
        createNotificationChannel()
        initNotificationBuilder()
    }


    funlaunchNotification(){
        with(NotificationManagerCompat.from(mContext)) {
            // notificationId is a unique int for each notification that you must define
            notificationManager.notify(0, notificationBuilder.build())
        }
    }

    privatefuncreateNotificationChannel() {
        // Create the NotificationChannel, but only on API 26+ because// the NotificationChannel class is new and not in the support libraryif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name = "Channel Name"val descriptionText = "Channel Description"val importance = NotificationManager.IMPORTANCE_DEFAULT
            val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
                description = descriptionText
            }
            // Register the channel with the systemval notifiManager: NotificationManager =
                mContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notifiManager.createNotificationChannel(channel)
        }
    }


    privatefuninitNotificationBuilder() {

        // Create an explicit intent for an Activity in your appval sampleIntent = Intent(mContext, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        }
        val pendingIntent: PendingIntent = PendingIntent.getActivity(mContext, 0, sampleIntent, 0)

        /***
         * Notice that the NotificationCompat.Builder constructor requires that you provide a channel ID.
         * This is required for compatibility with Android 8.0 (API level 26) and higher,
         * but is ignored by older versions.
         */
        notificationBuilder = NotificationCompat.Builder(mContext, CHANNEL_ID)
            .setSmallIcon(R.drawable.notification_icon)
            .setContentTitle("Notification Title")
            .setContentText("Notification Body Text, Notification Body Text")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            // Set the intent that will fire when the user taps the notification
            .setContentIntent(pendingIntent)
            // Automatically removes the notification when the user taps it.
            .setAutoCancel(true)
    }

}

AlarmUtils.kt

import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import java.util.*

classAlarmUtils(context: Context) {
    privatevar mContext = context
    privatevar alarmMgr: AlarmManager? = nullprivatevar alarmIntent: PendingIntent

    init {
        alarmMgr = mContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        alarmIntent = Intent(mContext, AlarmReceiver::class.java).let { mIntent ->
        // if you want more than one notification use different requestCode// every notification need different requestCode
            PendingIntent.getBroadcast(mContext, 100, mIntent, PendingIntent.FLAG_UPDATE_CURRENT)
        }
    }

    funinitRepeatingAlarm(){
        val calendar: Calendar = Calendar.getInstance().apply {
            timeInMillis = System.currentTimeMillis()
            set(Calendar.HOUR_OF_DAY, 10)
            set(Calendar.MINUTE, 0)
            set(Calendar.SECOND, 0)
        }

        alarmMgr?.setInexactRepeating(
            AlarmManager.RTC_WAKEUP,
            calendar.timeInMillis,
            AlarmManager.INTERVAL_DAY,
            alarmIntent
        )
    }

}

AlarmReceiver.kt

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent

classAlarmReceiver:BroadcastReceiver() {
    overridefunonReceive(context: Context?, mIntent: Intent?) {
        val notificationUtils = NotificationUtils(context!!)
        notificationUtils.launchNotification()
    }
}

AndroidManifest.xml

<receiverandroid:name=".AlarmReceiver" />

MainActivity.kt

val alarmUtils = AlarmUtils(this)
alarmUtils.initRepeatingAlarm()

Method 2

NotificationUtils.kt

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat

classNotificationUtils(context:Context) {

    privatevar mContext = context
    privatelateinitvar notificationBuilder: NotificationCompat.Builder
    val notificationManager = NotificationManagerCompat.from(mContext)
    privateval CHANNEL_ID = "My_Notification_Channel"init {
        createNotificationChannel()
        initNotificationBuilder()
    }


    funlaunchNotification(){
        with(NotificationManagerCompat.from(mContext)) {
            // notificationId is a unique int for each notification that you must define
            notificationManager.notify(0, notificationBuilder.build())
        }
    }

    privatefuncreateNotificationChannel() {
        // Create the NotificationChannel, but only on API 26+ because// the NotificationChannel class is new and not in the support libraryif (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name = "Channel Name"val descriptionText = "Channel Description"val importance = NotificationManager.IMPORTANCE_DEFAULT
            val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
                description = descriptionText
            }
            // Register the channel with the systemval notifiManager: NotificationManager =
                mContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notifiManager.createNotificationChannel(channel)
        }
    }


    privatefuninitNotificationBuilder() {

        // Create an explicit intent for an Activity in your appval sampleIntent = Intent(mContext, MainActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
        }
        val pendingIntent: PendingIntent = PendingIntent.getActivity(mContext, 0, sampleIntent, 0)

        /***
         * Notice that the NotificationCompat.Builder constructor requires that you provide a channel ID.
         * This is required for compatibility with Android 8.0 (API level 26) and higher,
         * but is ignored by older versions.
         */
        notificationBuilder = NotificationCompat.Builder(mContext, CHANNEL_ID)
            .setSmallIcon(R.drawable.notification_icon)
            .setContentTitle("Notification Title")
            .setContentText("Notification Body Text, Notification Body Text")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            // Set the intent that will fire when the user taps the notification
            .setContentIntent(pendingIntent)
            // Automatically removes the notification when the user taps it.
            .setAutoCancel(true)
    }

}

AlarmUtils.kt

import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import java.util.*

classAlarmUtils(context: Context) {
    privatevar mContext = context
    privatevar alarmMgr: AlarmManager? = nullprivatevar alarmIntent: PendingIntent

    init {
        alarmMgr = mContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        alarmIntent = Intent(mContext, AlarmReceiver::class.java).let { mIntent ->
        // if you want more than one notification use different requestCode// every notification need different requestCode
            PendingIntent.getBroadcast(mContext, 100, mIntent, PendingIntent.FLAG_UPDATE_CURRENT)
        }
    }

    funinitRepeatingAlarm(calendar: Calendar){
        calendar.apply {
            set(Calendar.HOUR_OF_DAY, 10)
            set(Calendar.MINUTE, 0)
            set(Calendar.SECOND, 0)
        }

        alarmMgr?.set(  AlarmManager.RTC_WAKEUP,
            calendar.timeInMillis,
            alarmIntent)
    }

AlarmReceiver.kt

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import java.util.*

    classAlarmReceiver:BroadcastReceiver() {
        overridefunonReceive(context: Context?, mIntent: Intent?) {
            val notificationUtils = NotificationUtils(context!!)
            notificationUtils.launchNotification()
    
            val calendar = Calendar.getInstance()
            calendar.add(Calendar.DAY_OF_YEAR, 1)
            val daysNextCalendar = calendar
            val alarmUtils = AlarmUtils(context)
            alarmUtils.initRepeatingAlarm(daysNextCalendar)
        }
    }

AndroidManifest.xml

<receiverandroid:name=".AlarmReceiver" />

MainActivity.kt

val calendar = Calendar.getInstance()
  val alarmUtils = AlarmUtils(this)
  alarmUtils.initRepeatingAlarm(calendar)

Reboot Device

If you want the alarm should work after rebooting the device you should do the following thing.

AlarmBootReceiver.kt

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import java.util.*

classAlarmBootReceiver : BroadcastReceiver(){

    overridefunonReceive(context: Context, intent: Intent) {
        if (intent.action == "android.intent.action.BOOT_COMPLETED") {
            val calendar = Calendar.getInstance()
            val alarmUtils = AlarmUtils(context)
            alarmUtils.initRepeatingAlarm(calendar)
        }
    }

}

AndroidManifest.xml

<uses-permissionandroid:name="android.permission.RECEIVE_BOOT_COMPLETED"/><receiverandroid:name=".AlarmBootReceiver"android:enabled="true"android:exported="true"><intent-filter><actionandroid:name="android.intent.action.BOOT_COMPLETED"/></intent-filter></receiver>

Post a Comment for "Send Daily Notification At A Scheduled Time Android"