fix(notifications): FG-Service-Notification und Nachrichten-Notification zu einer einzigen zusammenfassen #111

Closed
opened 2026-05-18 19:17:56 +00:00 by jreinemann-euris · 1 comment
jreinemann-euris commented 2026-05-18 19:17:56 +00:00 (Migrated from github.com)

Problem

Wenn MessagingService läuft und eine Nachricht eingeht, erscheinen zwei Notifications gleichzeitig im Shade:

  1. ID 9999 – "Warten auf Nachrichten…" (FG-Service, PRIORITY_MIN, setOngoing(true))
  2. ID senderId.hashCode() – "Neue Nachricht von X" (PRIORITY_HIGH, autoCancel)

Das ist UX-Spam.

Root cause: Android erzwingt für jeden Foreground Service eine sichtbare Notification. Beide Notifications entstehen unabhängig voneinander – die erste durch MessagingService.buildForegroundNotification(), die zweite durch NotificationHelper.showNewMessageNotification().


Lösung: Eine Notification für zwei Zustände

Die FG-Service-Notification (ID 9999) übernimmt beim Nachrichteneingang die Rolle der Nachrichten-Notification. Zu jedem Zeitpunkt ist genau eine Notification sichtbar.

Zustand Notification-Inhalt Channel Priority
Idle (horcht) "Warten auf Nachrichten…" SERVICE_CHANNEL_ID MIN
1 Nachricht eingegangen "Neue Nachricht von X" CHANNEL_ID HIGH
2+ Nachrichten "Neue Nachrichten von A und B" CHANNEL_ID HIGH
Nachricht geöffnet zurück auf Idle-Zustand SERVICE_CHANNEL_ID MIN

Technische Umsetzung

1. MessagingService.kt

  • NOTIFICATION_ID = 9999 aus dem private companion object in internal companion object verschieben (damit NotificationHelper darauf zugreifen kann)

2. NotificationHelper.kt

showNewMessageNotification():

  • Die Zeile notificationManager.notify(senderNotificationId, notification) entfällt
  • Stattdessen: notificationManager.notify(MessagingService.NOTIFICATION_ID, messageNotification)
  • messageNotification wird mit CHANNEL_ID (High-Importance) gebaut:
    • 1 aktiver Absender: contentText = "Neue Nachricht von $senderUsername", contentIntent → direkt in den Chat (wie bisher chatPendingIntent)
    • 2+ Absender: contentText = buildSummaryText(...), contentIntent → Nachrichten-Liste (wie bisher messagesPendingIntent)
  • setAutoCancel(false), setOngoing(true) (da FG-Notification)

cancelNotificationForSender() und cancelAllMessageNotifications():

  • notificationManager.cancel(senderNotificationId) entfällt (es gibt keine Sender-spezifischen Notification-IDs mehr)
  • Wenn nach dem Entfernen activeSenderNotificationIds leer ist → notificationManager.notify(MessagingService.NOTIFICATION_ID, buildIdleNotification()) aufrufen
  • buildIdleNotification(): neue private Hilfsmethode, die die gleiche Notification wie MessagingService.buildForegroundNotification() baut (oder MessagingService stellt eine statische Factory-Methode bereit)

updateBadgeCount():

  • Die Badge-Logik kann entfallen oder auf NOTIFICATION_ID (9999) umgestellt werden – da keine separaten Sender-IDs mehr existieren, ist sie redundant. Kann vorerst as-is bleiben, schadet nicht.

SUMMARY_NOTIFICATION_ID = 0 und Summary-Notification:

  • Die summaryNotification und shouldShowSummary-Logik entfällt (die FG-Notification übernimmt das zusammengefasste Anzeigen direkt)

3. NotificationHelperTest.kt

  • Tests für showNewMessageNotification() anpassen: erwartete Notification-ID ist jetzt 9999 statt senderId.hashCode()
  • Tests für cancelNotificationForSender() anpassen: prüfen dass Revert auf Idle-State passiert

Abnahme-Kriterien

  • Wenn MessagingService läuft und eine Nachricht eingeht: genau 1 Notification im Shade
  • Notification zeigt "Neue Nachricht von X" (1 Absender) bzw. "Neue Nachrichten von A und B" (2 Absender)
  • Tap auf Notification öffnet den Chat direkt (1 Absender) oder die Nachrichten-Liste (2+)
  • Nach Öffnen des Chats (cancelNotificationForSender): Notification wechselt zurück auf "Warten auf Nachrichten…"
  • Build und Unit-Tests grün (./gradlew :app:test)
## Problem Wenn `MessagingService` läuft und eine Nachricht eingeht, erscheinen **zwei Notifications gleichzeitig** im Shade: 1. `ID 9999` – "Warten auf Nachrichten…" (FG-Service, `PRIORITY_MIN`, `setOngoing(true)`) 2. `ID senderId.hashCode()` – "Neue Nachricht von X" (`PRIORITY_HIGH`, `autoCancel`) Das ist UX-Spam. **Root cause:** Android erzwingt für jeden Foreground Service eine sichtbare Notification. Beide Notifications entstehen unabhängig voneinander – die erste durch `MessagingService.buildForegroundNotification()`, die zweite durch `NotificationHelper.showNewMessageNotification()`. --- ## Lösung: Eine Notification für zwei Zustände Die FG-Service-Notification (`ID 9999`) übernimmt beim Nachrichteneingang die Rolle der Nachrichten-Notification. Zu jedem Zeitpunkt ist **genau eine Notification** sichtbar. | Zustand | Notification-Inhalt | Channel | Priority | |---|---|---|---| | Idle (horcht) | "Warten auf Nachrichten…" | `SERVICE_CHANNEL_ID` | MIN | | 1 Nachricht eingegangen | "Neue Nachricht von X" | `CHANNEL_ID` | HIGH | | 2+ Nachrichten | "Neue Nachrichten von A und B" | `CHANNEL_ID` | HIGH | | Nachricht geöffnet | zurück auf Idle-Zustand | `SERVICE_CHANNEL_ID` | MIN | --- ## Technische Umsetzung ### 1. `MessagingService.kt` - `NOTIFICATION_ID = 9999` aus dem `private companion object` in `internal companion object` verschieben (damit `NotificationHelper` darauf zugreifen kann) ### 2. `NotificationHelper.kt` **`showNewMessageNotification()`:** - Die Zeile `notificationManager.notify(senderNotificationId, notification)` **entfällt** - Stattdessen: `notificationManager.notify(MessagingService.NOTIFICATION_ID, messageNotification)` - `messageNotification` wird mit `CHANNEL_ID` (High-Importance) gebaut: - 1 aktiver Absender: `contentText = "Neue Nachricht von $senderUsername"`, `contentIntent` → direkt in den Chat (wie bisher `chatPendingIntent`) - 2+ Absender: `contentText = buildSummaryText(...)`, `contentIntent` → Nachrichten-Liste (wie bisher `messagesPendingIntent`) - `setAutoCancel(false)`, `setOngoing(true)` (da FG-Notification) **`cancelNotificationForSender()` und `cancelAllMessageNotifications()`:** - `notificationManager.cancel(senderNotificationId)` **entfällt** (es gibt keine Sender-spezifischen Notification-IDs mehr) - Wenn nach dem Entfernen `activeSenderNotificationIds` leer ist → `notificationManager.notify(MessagingService.NOTIFICATION_ID, buildIdleNotification())` aufrufen - `buildIdleNotification()`: neue private Hilfsmethode, die die gleiche Notification wie `MessagingService.buildForegroundNotification()` baut (oder `MessagingService` stellt eine statische Factory-Methode bereit) **`updateBadgeCount()`:** - Die Badge-Logik kann entfallen oder auf `NOTIFICATION_ID` (9999) umgestellt werden – da keine separaten Sender-IDs mehr existieren, ist sie redundant. Kann vorerst as-is bleiben, schadet nicht. **`SUMMARY_NOTIFICATION_ID = 0` und Summary-Notification:** - Die `summaryNotification` und `shouldShowSummary`-Logik **entfällt** (die FG-Notification übernimmt das zusammengefasste Anzeigen direkt) ### 3. `NotificationHelperTest.kt` - Tests für `showNewMessageNotification()` anpassen: erwartete Notification-ID ist jetzt `9999` statt `senderId.hashCode()` - Tests für `cancelNotificationForSender()` anpassen: prüfen dass Revert auf Idle-State passiert --- ## Abnahme-Kriterien - [ ] Wenn MessagingService läuft und eine Nachricht eingeht: **genau 1 Notification** im Shade - [ ] Notification zeigt "Neue Nachricht von X" (1 Absender) bzw. "Neue Nachrichten von A und B" (2 Absender) - [ ] Tap auf Notification öffnet den Chat direkt (1 Absender) oder die Nachrichten-Liste (2+) - [ ] Nach Öffnen des Chats (`cancelNotificationForSender`): Notification wechselt zurück auf "Warten auf Nachrichten…" - [ ] Build und Unit-Tests grün (`./gradlew :app:test`)
jreinemann-euris commented 2026-05-18 19:23:34 +00:00 (Migrated from github.com)

Implementierung abgeschlossen

FG-Service-Notification und Nachrichten-Notifications zu einer einzigen Notification (ID 9999) zusammengefasst.

Umsetzung

  • Eine Notification fuer alle Zustaende: Idle -> Nachricht(en) -> zurueck auf Idle
  • Idle: 'Warten auf Nachrichten...' (SERVICE_CHANNEL, PRIORITY_MIN)
  • 1 Absender: 'Neue Nachricht von X' (CHANNEL_ID, PRIORITY_HIGH, Tap oeffnet Chat)
  • 2+ Absender: 'Neue Nachrichten von A und B' (CHANNEL_ID, PRIORITY_HIGH, Tap oeffnet Liste)
  • cancelNotificationForSender setzt auf Idle zurueck wenn keine Absender mehr aktiv
## Implementierung abgeschlossen FG-Service-Notification und Nachrichten-Notifications zu einer einzigen Notification (ID 9999) zusammengefasst. ### Umsetzung - Eine Notification fuer alle Zustaende: Idle -> Nachricht(en) -> zurueck auf Idle - Idle: 'Warten auf Nachrichten...' (SERVICE_CHANNEL, PRIORITY_MIN) - 1 Absender: 'Neue Nachricht von X' (CHANNEL_ID, PRIORITY_HIGH, Tap oeffnet Chat) - 2+ Absender: 'Neue Nachrichten von A und B' (CHANNEL_ID, PRIORITY_HIGH, Tap oeffnet Liste) - cancelNotificationForSender setzt auf Idle zurueck wenn keine Absender mehr aktiv
Sign in to join this conversation.
No description provided.