Describe the bug
activeNotifications in NotificationDismissalUtil is only populated from onNotificationPosted (MediaNotificationListener.kt:668). onListenerConnected() (line 448) doesn't repopulate it from getActiveNotifications().
After the app's process restarts — system kill, reboot, re-toggling notification access — notifications that are still sitting in the shade are no longer in the map. Dismissals and actions for them fail with Notification with ID ... not found, while the Mac app still lists them and reports success, so from the user's side it just silently does nothing.
To Reproduce
- Connect and let some notifications sync
- Force stop the app (or reboot the phone), then let it reconnect
- From the Mac app, dismiss one of the notifications that arrived before the restart — nothing happens, logcat shows
Notification with ID <id> not found
- Dismiss a notification that arrived after the restart — works
Expected behavior
Notifications that are still active on the phone stay actionable after the listener reconnects.
Suggested fix
Repopulating the map in onListenerConnected() from getActiveNotifications() is necessary, but on its own it isn't enough — I originally assumed it would be and that turned out to be wrong on device (correction below).
Generated IDs embed postTime, and within a session the first-seen ID is preserved across updates through keyToId. Once that in-memory map is gone, regenerating from the current postTime yields a different ID than the one the client is holding, so its requests still miss. Observed after a restart: the same notification was re-registered as ..._-858577043_1785507992750 while the client still held ..._-858577043_1785507236727 — same package, same title hash, newer postTime.
For IDs to keep resolving, they have to survive the restart as well. Two ways: persist the key -> id mapping (sbn.key is stable across updates and restarts) and consult it when re-registering, or stop embedding postTime in the ID altogether (deriving it from sbn.key), which is protocol-visible and a bigger call.
Environment
- Device: Samsung Galaxy Z Fold7 (SM-F966B)
- Android Version: 16
- App Version: 4.0.0 (versionCode 30) — Mac app 4.0.0
Additional context
Found while debugging #136 (separate root cause — that one affects action buttons even on freshly posted notifications). Verified with dumpsys notification: dismissing a freshly posted notification took the YouTube count from 20 to 18, while the same call on an older ID did nothing — so the dismissal path itself is fine, it's the lookup table that's empty.
Describe the bug
activeNotificationsinNotificationDismissalUtilis only populated fromonNotificationPosted(MediaNotificationListener.kt:668).onListenerConnected()(line 448) doesn't repopulate it fromgetActiveNotifications().After the app's process restarts — system kill, reboot, re-toggling notification access — notifications that are still sitting in the shade are no longer in the map. Dismissals and actions for them fail with
Notification with ID ... not found, while the Mac app still lists them and reports success, so from the user's side it just silently does nothing.To Reproduce
Notification with ID <id> not foundExpected behavior
Notifications that are still active on the phone stay actionable after the listener reconnects.
Suggested fix
Repopulating the map in
onListenerConnected()fromgetActiveNotifications()is necessary, but on its own it isn't enough — I originally assumed it would be and that turned out to be wrong on device (correction below).Generated IDs embed
postTime, and within a session the first-seen ID is preserved across updates throughkeyToId. Once that in-memory map is gone, regenerating from the currentpostTimeyields a different ID than the one the client is holding, so its requests still miss. Observed after a restart: the same notification was re-registered as..._-858577043_1785507992750while the client still held..._-858577043_1785507236727— same package, same title hash, newerpostTime.For IDs to keep resolving, they have to survive the restart as well. Two ways: persist the
key -> idmapping (sbn.keyis stable across updates and restarts) and consult it when re-registering, or stop embeddingpostTimein the ID altogether (deriving it fromsbn.key), which is protocol-visible and a bigger call.Environment
Additional context
Found while debugging #136 (separate root cause — that one affects action buttons even on freshly posted notifications). Verified with
dumpsys notification: dismissing a freshly posted notification took the YouTube count from 20 to 18, while the same call on an older ID did nothing — so the dismissal path itself is fine, it's the lookup table that's empty.