Skip to content

[various] Add support for notification dismissed callbacks - #2790

Merged
MaikuB merged 2 commits into
MaikuB:masterfrom
vlaushkin:feature/notification-dismissed-callback
Jul 24, 2026
Merged

[various] Add support for notification dismissed callbacks#2790
MaikuB merged 2 commits into
MaikuB:masterfrom
vlaushkin:feature/notification-dismissed-callback

Conversation

@vlaushkin

@vlaushkin vlaushkin commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Resolves #74.

Summary

  • Adds the ability to be notified when a user dismisses a notification (swipes it away or clears it), reported through the existing response callbacks with a new NotificationResponseType.notificationDismissed. No new callback is introduced.
  • Android: opt-in via a dismissIsolate preference (NotificationDismissedIsolate.main / .background) on AndroidNotificationDetails. background registers a delete intent that broadcasts to the existing ActionBroadcastReceiver, so dismissals go through the same background-isolate pipeline as notification actions and work even when the app has been terminated (the concern that blocked [flutter_local_notifications] Added callback for dismissing a notification #722); main delivers to the running app instead.
  • iOS/macOS: the same preference on DarwinNotificationDetails, for categories configured with the customDismissAction option. macOS has no background isolate ([macOS] Launch isolate with an entrypoint from another library? flutter/flutter#65222), so it always reports on the main isolate.

Notes

  • On Android the delete intent also fires when the system removes the notification (e.g. timeoutAfter), so it is slightly broader than a user swipe. Tapping a notification or cancelling it programmatically does not emit it.

Test plan

  • cd flutter_local_notifications && flutter test (added tests covering the preference being sent over the channel, its default, and a dismissed response decoding to the new type).
  • Manual: the example app has two buttons (main / background); verified end-to-end on Android (Pixel 8a), the iOS Simulator (iPhone SE) and macOS 15.7, including when the app is terminated.

@vlaushkin vlaushkin changed the title [flutter_local_notifications] Add support for notification dismissed callbacks [various] Add support for notification dismissed callbacks Jun 23, 2026

@MaikuB MaikuB left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. I tested this out and it works great. I had the following questions

  • There are a couple of inconsistencies with how Android and iOS behave. Android always triggers the callback via background isolate whilst on iOS, it depends on how the notification was configured. If I tweaked the example app a bit, the callback can be on the background isolate on iOS instead. Would it be possible/feasible to make use of a parameter common across Android and iOS that gives developers the option on which isolate the prefer the dismissal to fire on? This could be made opt in and replace emitDismissEvent. I'm thinking something like an enum and is treated as a "preference" in that when specifying a background isolate is to be used, for platforms that don't support it (e.g. macOS), it'll fallback to the main isolate
  • If the above is possible, can you update the example app to show the additional use cases? If it's not possible then is there a way to update the example app so that there's a scenario that shows iOS firing the callback on a background isolate?
  • To help avoid confusion, I would suggest the print entry used on background isolate and main isolate have the text updated around which isolate was used

Edit: the iOS error isn't due to this PR. I'll see if I can fix this up

@vlaushkin

Copy link
Copy Markdown
Contributor Author

Thanks for the review!

I've added a dismissIsolate preference (NotificationDismissedIsolate.main / .background) to both AndroidNotificationDetails and DarwinNotificationDetails. Each value maps to a single isolate: main fires on the main isolate (only while the app is running) and background on the background isolate (works even when the app has been terminated). macOS has no background isolate, so it always reports on the main isolate.

I did consider falling back from main to the background isolate when the app is terminated, but left it out: it makes the same configuration behave differently depending on app state, and it doesn't fit how the plugin already picks the isolate statically (as with notification actions). So the only fallback is the macOS one you described.

The example now has two buttons (main / background), and the print states which isolate the dismissal fired on.

I've verified the full main/background × running/terminated matrix on Android, iOS and macOS.

@MaikuB

MaikuB commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Thanks for making the changes

I did consider falling back from main to the background isolate when the app is terminated, but left it out: it makes the same configuration behave differently depending on app state, and it doesn't fit how the plugin already picks the isolate statically (as with notification actions). So the only fallback is the macOS one you described.

Yeah I was really referring to macOS when I called this out so all good.

I'll get back to you once I have given this a spin but one thing that came to mind is that since your changes mean specifying a preference is possible, I'm questioning if it would be better to make the default behaviour be that it notifies on main isolate without having to opt in. What's your thoughts on that? My thinking is it may allow some apps with existing scheduled notifications to handle dismissals in some form and potentially less effort for plugin consumers to get this setup. The latter assumes that most will want to do something when the app is running though I don't know how realistic that is.

Another thing to note is I addressed the iOS integration test issue as part of #2793. Can you update your fork/branch?

vlaushkin added 2 commits July 7, 2026 21:06
Resolves MaikuB#74. Adds an opt-in `emitDismissEvent` flag to
`AndroidNotificationDetails` and maps iOS/macOS dismissals (for categories
configured with `customDismissAction`) to a new
`NotificationResponseType.notificationDismissed`. The dismissal is delivered
through the existing notification response callbacks, reusing the background
isolate pipeline already used for notification actions.
…missal callback

Adds a `dismissIsolate` preference (`NotificationDismissedIsolate`) to the
platform-specific details, replacing the boolean flag, so apps can choose
whether a dismissal fires on the main or a background isolate. Where a platform
can't honour the choice it degrades: macOS has no background isolate so it
always reports on the main isolate, and the main isolate only fires while the
app is running.
@vlaushkin
vlaushkin force-pushed the feature/notification-dismissed-callback branch from 3dbe8f2 to cf8d389 Compare July 7, 2026 18:09
@vlaushkin

Copy link
Copy Markdown
Contributor Author

I've rebased the branch onto the latest master, so it now includes your iOS integration fix (#2793).

On the default question: my vote is to keep it opt-in. iOS/macOS only deliver a dismissal when the category has customDismissAction, so it can't be on by default there without opting in anyway; defaulting only Android to on would bring back the Android/iOS inconsistency the preference was meant to remove. Happy to revisit if you feel differently after a spin.

@MaikuB
MaikuB merged commit ca41f01 into MaikuB:master Jul 24, 2026
73 of 76 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Callback when notification is dismissed by user

2 participants