Open In App

How to Schedule Notifications in Android?

Last Updated : 14 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In this article, we will see the process of scheduling notifications in Android for specific dates and times and also it can run both in the foreground and background. This is particularly valuable when developing apps that allow users to be notified of events at predefined moments enhancing the overall user experience. A sample video is given below to get an idea about what we will do in this article.

Step-by-Step Implementation

Step 1: Create a New Project in Android Studio

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio.

Note: we are using Kotlin as the programming language.

Step 2:

Open the AndroidMainfest File and Add Permissions For Notifications and Alarm that will be used to schedule Notifications

XML




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


Step 3:

We have created the basic layout for the Date and Time Picker just for demonstration purposes.

activity_main.xml:

XML




<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">
  
    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingHorizontal="20dp"
        android:layout_marginTop="20dp"
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense">
  
        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/title" />
  
    </com.google.android.material.textfield.TextInputLayout>
  
    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingHorizontal="20dp"
        android:layout_marginTop="20dp"
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense">
  
        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/message"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/message" />
  
    </com.google.android.material.textfield.TextInputLayout>
  
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp">
  
        <DatePicker
            android:id="@+id/datePicker"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:datePickerMode="spinner"
            android:calendarViewShown="false"
            android:layout_gravity="center"
            android:scaleY="0.7"
            android:scaleX="0.7"
            android:layout_marginLeft="-30dp"
            android:layout_marginRight="-30dp"
            />
        
        <TimePicker
            android:id="@+id/timePicker"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:timePickerMode="spinner"
            android:layout_gravity="center"
            android:scaleY="0.7"
            android:scaleX="0.7"
            android:layout_marginLeft="-30dp"
            android:layout_marginRight="-30dp"/>
    </LinearLayout>
  
    <Button
        android:id="@+id/submitButton"
        android:layout_marginTop="20dp"
        android:layout_gravity="center"
        android:text="@string/schedule_notification"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
  
</LinearLayout>


UI Output:

activitymain1

activity_main.xml

Step 4:

We are using view binding in this project you can also declare your views by findviewbyid to enable view binding navigate to Gradle Script > build.gradle(module) and add this.

viewBinding {
enabled = true
}

Step 5:

Create New Kotlin Class this Kotlin class will be a BroadcastReceiver that is designed to handle incoming broadcasts and display a notification.

Notification.kt:

Kotlin




package com.ayush.assignment
  
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationCompat
  
// Constants for notification
const val notificationID = 121
const val channelID = "channel1"
const val titleExtra = "titleExtra"
const val messageExtra = "messageExtra"
  
// BroadcastReceiver for handling notifications
class Notification : BroadcastReceiver() {
  
    // Method called when the broadcast is received
    override fun onReceive(context: Context, intent: Intent) {
  
        // Build the notification using NotificationCompat.Builder
        val notification = NotificationCompat.Builder(context, channelID)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentTitle(intent.getStringExtra(titleExtra)) // Set title from intent
            .setContentText(intent.getStringExtra(messageExtra)) // Set content text from intent
            .build()
  
        // Get the NotificationManager service
        val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
  
        // Show the notification using the manager
        manager.notify(notificationID, notification)
    }
}


After creating class navigate to AndroidMainfest again and add this Broadcast Receiver Class that we created above in my case class name is Notification

<receiver
android:name=".Notification"
android:enabled="true"/>

Step 6:

Navigate to the Kotlin file corresponding to your layout. In the Kotlin code,users can input notification details. Upon clicking the “Submit” button the app schedules a notification after obtaining notification permissions. The scheduled notification is set to be displayed at the specified time by a confirmation dialog presenting notification details.

MainActivity.kt:

Kotlin




package com.geeksforgeeks.app
  
import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.AlertDialog
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import com.ayush.assignment.databinding.ActivityMainBinding
import java.util.Calendar
import java.util.Date
  
class MainActivity : AppCompatActivity() {
  
    private lateinit var binding: ActivityMainBinding
  
    @RequiresApi(Build.VERSION_CODES.O)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
  
        createNotificationChannel()
  
        // Set onClickListener for the submit button
        binding.submitButton.setOnClickListener {
            // Check if notification permissions are granted
            if (checkNotificationPermissions(this)) {
                // Schedule a notification
                scheduleNotification()
            }
        }
    }
  
    @SuppressLint("ScheduleExactAlarm")
    private fun scheduleNotification() {
        // Create an intent for the Notification BroadcastReceiver
        val intent = Intent(applicationContext, Notification::class.java)
  
        // Extract title and message from user input
        val title = binding.title.text.toString()
        val message = binding.message.text.toString()
  
        // Add title and message as extras to the intent
        intent.putExtra(titleExtra, title)
        intent.putExtra(messageExtra, message)
  
        // Create a PendingIntent for the broadcast
        val pendingIntent = PendingIntent.getBroadcast(
            applicationContext,
            notificationID,
            intent,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )
  
        // Get the AlarmManager service
        val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
  
        // Get the selected time and schedule the notification
        val time = getTime()
        alarmManager.setExactAndAllowWhileIdle(
            AlarmManager.RTC_WAKEUP,
            time,
            pendingIntent
        )
  
        // Show an alert dialog with information 
          // about the scheduled notification
        showAlert(time, title, message)
    }
  
    private fun showAlert(time: Long, title: String, message: String) {
        // Format the time for display
        val date = Date(time)
        val dateFormat = android.text.format.DateFormat.getLongDateFormat(applicationContext)
        val timeFormat = android.text.format.DateFormat.getTimeFormat(applicationContext)
  
        // Create and show an alert dialog with notification details
        AlertDialog.Builder(this)
            .setTitle("Notification Scheduled")
            .setMessage(
                "Title: $title\nMessage: $message\nAt: ${dateFormat.format(date)} ${timeFormat.format(date)}"
            )
            .setPositiveButton("Okay") { _, _ -> }
            .show()
    }
  
    private fun getTime(): Long {
        // Get selected time from TimePicker and DatePicker
        val minute = binding.timePicker.minute
        val hour = binding.timePicker.hour
        val day = binding.datePicker.dayOfMonth
        val month = binding.datePicker.month
        val year = binding.datePicker.year
  
        // Create a Calendar instance and set the selected date and time
        val calendar = Calendar.getInstance()
        calendar.set(year, month, day, hour, minute)
  
         
        return calendar.timeInMillis
    }
  
    @RequiresApi(Build.VERSION_CODES.O)
    private fun createNotificationChannel() {
        // Create a notification channel for devices running
          // Android Oreo (API level 26) and above
        val name = "Notify Channel"
        val desc = "A Description of the Channel"
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(channelID, name, importance)
        channel.description = desc
  
        // Get the NotificationManager service and create the channel
        val notificationManager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(channel)
    }
  
    fun checkNotificationPermissions(context: Context): Boolean {
        // Check if notification permissions are granted
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val notificationManager =
                context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
  
            val isEnabled = notificationManager.areNotificationsEnabled()
  
            if (!isEnabled) {
                // Open the app notification settings if notifications are not enabled
                val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
                intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
                context.startActivity(intent)
  
                return false
            }
        } else {
            val areEnabled = NotificationManagerCompat.from(context).areNotificationsEnabled()
  
            if (!areEnabled) {
                // Open the app notification settings if notifications are not enabled
                val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
                intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
                context.startActivity(intent)
  
                return false
            }
        }
  
        // Permissions are granted
        return true
    }
}


Output:



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads