No Delay in reciving Notification for Task Expiration in Android To-Do List App Project

Dev@C2004

New member
Jul 15, 2023
2
3
3
Visit site
I want to set a notification for each item in my to-do list when it is about to expire in the next 5 minutes or before the expiration time. However, in the current implementation, the notification is showing instantly after adding a task to the to-do list. How can I prevent this error?

example : The current time is 6:00 pm expiration time is 6:30 pm , so the notification should appear at 6:25 pm even if the app is closed.

But notification is Appearing at instant of adding the task , like if its expiration time is very far away, still showing notification expired.

Please Give Suggestions to fix this issue.

Here is My Impelementation Logic

NotificationWroker Class

package com.example.todolist //imports

class NotificationWorker( private val context: Context, workerParams: WorkerParameters ) : Worker(context, workerParams) {

override fun doWork(): Result {
// Retrieve the task details from input data
val taskId = inputData.getLong("taskId", -1)
val taskName = inputData.getString("taskName")
val expirationTime = inputData.getString("expirationTime")

// Check if the app has the required permission to post notifications
if (ContextCompat.checkSelfPermission(
context,
Manifest.permission.POST_NOTIFICATIONS
) != PackageManager.PERMISSION_GRANTED
) {
// Permission not granted, handle the situation (e.g., show a message or request permission)
// You can implement your own logic here based on your app's requirements
// For example, you can show a message to the user or request the permission
// using a dialog or an in-app prompt.
// Remember to handle the permission request response as well.
return Result.failure()
}

// Create the notification channel if it doesn't exist
createNotificationChannel()

// Create the notification
val notification = NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle("Task Expired")
.setContentText("Task '$taskName' has expired!")
.setSmallIcon(R.drawable.bar_icon)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.build()

// Show the notification
val notificationManager = NotificationManagerCompat.from(context)
notificationManager.notify(taskId.toInt(), notification)

return Result.success()
}

private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
CHANNEL_ID,
"Task Notifications",
NotificationManager.IMPORTANCE_HIGH
)
channel.description = "Channel for task notifications"

val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}

companion object {
private const val CHANNEL_ID = "task_notification_channel"
}

}

MainActivity Code(Only the Required Portion)

addSaveBtn.setOnClickListener {

//edit task
if (et_item.text.isNotEmpty()) {
id++
var taskName = et_item.text.toString()
var category = categorySelected
if (time_tv.text.isNotEmpty()) {
var time = time_tv.text.toString()
var format = SimpleDateFormat("E, MMM d, yyyy", Locale.getDefault())
var date = format.format(Date())
val todo = TodoData(
id,
taskName,
false,
time,
date,
category,
isExpired = false,
isNotified = false
)
CoroutineScope(Dispatchers.Main).launch {
withContext(Dispatchers.IO) {
todoDao.insert(todo)
}
//scheduleLing
scheduleNotification(id,taskName,time)
}

todoList.add(todo)
Log.i("Add", "$todo")
todoAdapter.notifyItemInserted(todoList.size)
bottomDialog.dismiss()
emptyImg = findViewById(R.id.imageView)
if (todoList.size == 0)
emptyImg.visibility = View.VISIBLE
else
emptyImg.visibility = View.INVISIBLE
} else {
val snackBar = Snackbar.make(
addTaskLl, "Please Select Due Time!",
Snackbar.LENGTH_LONG
).setAction("Action", null)
snackBar.setActionTextColor(Color.WHITE)
val snackBarView = snackBar.view
snackBarView.setBackgroundColor(Color.RED)
val textView =
snackBarView.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
textView.setTextColor(Color.WHITE)
snackBar.show()
}

} else {
val snackBar = Snackbar.make(
addTaskLl, "Task item Can't be Empty!",
Snackbar.LENGTH_LONG
).setAction("Action", null)
snackBar.setActionTextColor(Color.WHITE)
val snackBarView = snackBar.view
snackBarView.setBackgroundColor(Color.RED)
val textView =
snackBarView.findViewById(com.google.android.material.R.id.snackbar_text) as TextView
textView.setTextColor(Color.WHITE)
snackBar.show()
}

}
// bottomDialog.setCancelable(false)
bottomDialog.setContentView(view)

bottomDialog.show()
}

}

Scheduling Function (present in the MainActivity Class)

private fun scheduleNotification(taskId: Long, taskName: String, expirationTime: String) {
val workManager = WorkManager.getInstance(applicationContext)

// Parse the expiration time string to a Date object
val format = SimpleDateFormat("hh:mm a", Locale.getDefault())
val expirationDate = format.parse(expirationTime)

// Calculate the delay before showing the notification (5 minutes)
val notificationDelay = 5 * 60 * 1000 // 5 minutes in milliseconds

// Calculate the expiration time in milliseconds
val expirationMillis = expirationDate?.time ?: return

// Calculate the notification time by subtracting the delay from the expiration time
val notificationTime = expirationMillis - notificationDelay

// Build the input data
val inputData = Data.Builder()
.putLong("taskId", taskId)
.putString("taskName", taskName)
.build()

// Create a OneTimeWorkRequest with input data and delay
val notificationWorkRequest = OneTimeWorkRequestBuilder<NotificationWorker>()
.setInputData(inputData)
.setInitialDelay(notificationTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS)
.build()

// Enqueue the work request with a unique tag
workManager.enqueueUniqueWork(
"notification_$taskId",
ExistingWorkPolicy.REPLACE,
notificationWorkRequest
)
}

Except those Two more Functions are Implemented in Adapter Class to Cancel the Notification for the item which is expired or deleted.
 

Trending Posts

Forum statistics

Threads
943,202
Messages
6,917,785
Members
3,158,873
Latest member
dxter