From 6c0a818b6214c1cf52d39e4422ce4ce77958f63f Mon Sep 17 00:00:00 2001 From: avebeatrix Date: Sun, 24 May 2026 01:18:58 +0300 Subject: [PATCH] fix(notification): cancel() crashes on Android with empty notifications list (fix #2341) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `cancel` Android command parses `CancelArgs.notifications` as a `lateinit var List`, but the JS `cancelAll()` API and the Rust SDK's `NotificationExt::cancel_all()` both dispatch the `cancel` command with no arguments. The handler then throws `UninitializedPropertyAccessException` when it reads `args.notifications`, which on the JS side surfaces as a rejected `invoke()` promise that the polyfill silently swallows — so callers see no notifications cancelled and no error. Make `notifications` an optional list defaulting to `[]`, and route an empty list through a new `TauriNotificationManager.cancelAll()` that enumerates saved IDs from `NotificationStorage.getSavedNotificationIds()` and reuses the existing `cancel()` cleanup path (dismiss visible + cancel timer + delete storage entry). Reported in #2341. --- .changes/notification-cancel-all-android.md | 6 ++++++ .../android/src/main/java/NotificationPlugin.kt | 8 ++++++-- .../android/src/main/java/TauriNotificationManager.kt | 4 ++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 .changes/notification-cancel-all-android.md diff --git a/.changes/notification-cancel-all-android.md b/.changes/notification-cancel-all-android.md new file mode 100644 index 0000000000..fee83deb1b --- /dev/null +++ b/.changes/notification-cancel-all-android.md @@ -0,0 +1,6 @@ +--- +"notification": patch +"notification-js": patch +--- + +Fix `cancel` command crashing on Android with `UninitializedPropertyAccessException` when invoked with no `notifications` argument — i.e. when the JS `cancelAll()` API or the Rust `NotificationExt::cancel_all()` SDK method is used. `CancelArgs.notifications` is now an optional list defaulting to `[]`; the handler routes an empty list to a new `TauriNotificationManager.cancelAll()` that enumerates saved notification IDs from storage and cancels each. diff --git a/plugins/notification/android/src/main/java/NotificationPlugin.kt b/plugins/notification/android/src/main/java/NotificationPlugin.kt index 3ead31527b..07c545d795 100644 --- a/plugins/notification/android/src/main/java/NotificationPlugin.kt +++ b/plugins/notification/android/src/main/java/NotificationPlugin.kt @@ -39,7 +39,7 @@ class BatchArgs { @InvokeArg class CancelArgs { - lateinit var notifications: List + var notifications: List = listOf() } @InvokeArg @@ -152,7 +152,11 @@ class NotificationPlugin(private val activity: Activity): Plugin(activity) { @Command fun cancel(invoke: Invoke) { val args = invoke.parseArgs(CancelArgs::class.java) - manager.cancel(args.notifications) + if (args.notifications.isEmpty()) { + manager.cancelAll() + } else { + manager.cancel(args.notifications) + } invoke.resolve() } diff --git a/plugins/notification/android/src/main/java/TauriNotificationManager.kt b/plugins/notification/android/src/main/java/TauriNotificationManager.kt index a8912739bb..401c0d1db7 100644 --- a/plugins/notification/android/src/main/java/TauriNotificationManager.kt +++ b/plugins/notification/android/src/main/java/TauriNotificationManager.kt @@ -391,6 +391,10 @@ class TauriNotificationManager( } } + fun cancelAll() { + cancel(storage.getSavedNotificationIds().mapNotNull { it.toIntOrNull() }) + } + private fun cancelTimerForNotification(notificationId: Int) { val intent = Intent(context, TimedNotificationPublisher::class.java) var flags = 0