如何在Kotlin中取消一个已安排的本地通知?

huangapple go评论59阅读模式
英文:

How to cancel a scheduled local notification in Kotlin?

问题

I have an app where the user creates its own local notifications. User declares name, date and time the notification should popup and specifies the repeating frequency.
Then the notifications are listed in a recyclerview in another fragment.
The user is able to delete notification by swiping its recyclerview item to the left.

But when I create a notification, delete it then it still pops up at the specified time.

I am storing the notificationID in SharedPreferences as a date when its created (so that I can store it in my DB). I am passing it as a string with putExtra to my BroadcastReceiver class, I am getting the notificationID as a String in my BroadcastReceiver class with getStringExtra. Then passing the same notificationID.toInt() to my pendingIntent.getActivity. Then in my Fragment with recyclerView I am passing the same notificationID for cancelling and it still doesn't cancel.

Perhaps I'm using wrong flags?
Thanks a lot for any help.

Here's my BroadcastReceiver class:

const val titleExtra = "titleExtra"
const val descriptionExtra = "descriptionExtra"
val notificationID = "notificationID"

class Notification: BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {

        val intentToRepeat = Intent(context, MainActivity::class.java)
        val id = intent.getStringExtra(notificationID).toString()
        val pendingIntent = PendingIntent.getActivity(context, id.toInt(), intentToRepeat, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)

        val notification = NotificationCompat.Builder(context, channelID)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentTitle(intent.getStringExtra(titleExtra))
            .setContentText(intent.getStringExtra(descriptionExtra))
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
            .build()

        val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        if (intent.action == "cancel") {
            manager.cancel(id.toInt())
        }
        else {
            manager.notify(id.toInt(), notification)
        }
    }
}

My AndroidManifest:

<receiver android:name=".powiadomienia.Powiadomienie" android:enabled="true" 
          android:exported="false">
          <intent-filter>
                <action android:name="cancel"/>
                <action android:name="create" />
          </intent-filter>
</receiver>

In my recyclerview with notifications listed:

val currentNotification: SetNotification = listAdapter.getNotificationByPosition(viewHolder.bindingAdapterPosition)
if(direction == ItemTouchHelper.LEFT) {
    val alarmManager = requireActivity().getSystemService(Context.ALARM_SERVICE) as AlarmManager
    val intent = Intent(requireContext(), Notification::class.java)
    intent.action = "cancel"
    val pendingIntent = PendingIntent.getService(requireContext(), currentNotification.notificationId!!.toInt(), intent, PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE)
    pendingIntent?.let { _pendingIntent ->
        alarmManager.cancel(_pendingIntent)
    }
}

Neither manager.cancel() nor alarmManager.cancel() works.

The notification creates but how to cancel it?!

英文:

I have an app where the user creates its own local notifications. User declares name, date and time the nofication should popup and specifies the repeating frequency.
Then the notifications are listed in a recyclerview in another fragment.
The user is able to delete notification by swiping its recyclerview item to the left.

But when I create a notification, delete it then it still pops up at the specified time.

I am storing the notificationID in SharedPreferences as a date when its created (so that I can store it in my DB). I am passing it as a string with putExtra to my BroadcastReceiver class, I am getting the notificationID as a String in my BroadcastReceiver class with getStringExtra. Then passing the same notificationID.toInt() to my pendingIntent.getActivity. Then in my Fragment with recyclerView I am passing the same notificationID for cancelling and it still doesn't cancel.

Perhaps I'm using wrong flags?
Thanks a lot for any help.

Here's my BroadcastReceiver class:

const val titleExtra = &quot;titleExtra&quot;
const val descriptionExtra = &quot;descriptionExtra&quot;
val notificationID = &quot;notificationID&quot;

class Notification: BroadcastReceiver() {


    override fun onReceive(context: Context, intent: Intent) {


        val intentToRepeat = Intent(context, MainActivity::class.java)
        val id = intent.getStringExtra(notificationID).toString()
        val pendingIntent = PendingIntent.getActivity(context, id.toInt(), intentToRepeat, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)

        val notification = NotificationCompat.Builder(context, channelID)
            .setSmallIcon(R.drawable.ic_launcher_foreground)
            .setContentTitle(intent.getStringExtra(titleExtra))
            .setContentText(intent.getStringExtra(descriptionExtra))
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)
            .build()


        val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        if (intent.action == &quot;cancel&quot;) {
            manager.cancel(id.toInt())
        }
        else {
            manager.notify(id.toInt(), notification)
        }

    }
}

My AndroidManifest:

&lt;receiver android:name=&quot;.powiadomienia.Powiadomienie&quot; android:enabled=&quot;true&quot; 
          android:exported=&quot;false&quot;&gt;
          &lt;intent-filter&gt;
                &lt;action android:name=&quot;cancel&quot;/&gt;
                &lt;action android:name=&quot;create&quot; /&gt;
          &lt;/intent-filter&gt;
&lt;/receiver&gt;

In my recyclerview with notifications listed:

val currentNotification: SetNotification = listAdapter.getNotificationByPosition(viewHolder.bindingAdapterPosition)
if(direction == ItemTouchHelper.LEFT) {

                        // CANCEL
                        //val manager = requireContext().getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
                        //manager.cancel(currentPowiadomienie.notificationId!!)


                    val alarmManager = requireActivity().getSystemService(Context.ALARM_SERVICE) as AlarmManager

                    val intent = Intent(requireContext(), Notification::class.java)
                    intent.action = &quot;cancel&quot;
                    val pendingIntent = PendingIntent.getService(requireContext(), currentNotification.notificationId!!.toInt(), intent, PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE)
                    pendingIntent?.let { _pendingIntent -&gt;
                        alarmManager.cancel(_pendingIntent)
                    }

Neither manager.cancel() nor alarmManager.cancel() works.

The notification creates but how to cancel it?!

答案1

得分: 0

我认为你需要在调用alarmManager.cancel()之后调用notifydatasetchanged()方法,就像这样:

val currentNotification: SetNotification =
    listAdapter.getNotificationByPosition(viewHolder.bindingAdapterPosition)
if (direction == ItemTouchHelper.LEFT) {
    val alarmManager =
        requireActivity().getSystemService(Context.ALARM_SERVICE) as AlarmManager
    val intent = Intent(requireContext(), Notification::class.java)
    intent.action = "cancel"
    val pendingIntent = PendingIntent.getService(
        requireContext(),
        currentNotification.notificationId!!.toInt(),
        intent,
        PendingIntent.FLAG_CANCEL_CURRENT or
        PendingIntent.FLAG_IMMUTABLE
    )
    pendingIntent?.let { _pendingIntent ->
        alarmManager.cancel(_pendingIntent)
        notifyDataSetChanged()
    }
}
英文:

I think you need to call notifydatasetchanged() method after the alarmManager.cancel() like this:

val currentNotification: SetNotification = 
 listAdapter.getNotificationByPosition(viewHolder.bindingAdapterPosition)
if(direction == ItemTouchHelper.LEFT) {
    val alarmManager = 
        requireActivity().getSystemService(Context.ALARM_SERVICE) as AlarmManager
    val intent = Intent(requireContext(), Notification::class.java)
    intent.action = &quot;cancel&quot;
    val pendingIntent = PendingIntent.getService(requireContext(), 
        currentNotification.notificationId!!.toInt(), intent, 
        PendingIntent.FLAG_CANCEL_CURRENT or 
        PendingIntent.FLAG_IMMUTABLE)
        pendingIntent?.let { _pendingIntent -&gt;
            alarmManager.cancel(_pendingIntent)
            notifyDataSetChanged()
        }

答案2

得分: 0

我已解决了不取消来自通知的问题:

我认为我传递了错误的上下文。检查一下是否传递了正确的上下文。

要取消通知:

private fun removeAlarm(id: Int){
        val alarmManager = activity?.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        // Notification = BroadcastReceiver class
        val intent = Intent(requireContext(), Notification::class.java)
        val pendingIntent = PendingIntent.getBroadcast(requireContext(), id, intent, PendingIntent.FLAG_IMMUTABLE)
        alarmManager.cancel(pendingIntent)
    }
英文:

I've solved my issue for not canceling coming notifications:

I think I was passing the wrong context. Check if you're passing the right one

To cancel a notification:

private fun removeAlarm(id: Int){
        val alarmManager = activity?.getSystemService(Context.ALARM_SERVICE) as AlarmManager
        // Notification = BroadcastReceiver class
        val intent = Intent(requireContext(), Notification::class.java)
        val pendingIntent = PendingIntent.getBroadcast(requireContext(), id, intent, PendingIntent.FLAG_IMMUTABLE)
        alarmManager.cancel(pendingIntent)
    }

huangapple
  • 本文由 发表于 2023年1月9日 09:11:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75052406.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定