From 6eb7d79ed04850c0628cc789bb1b26bf337e0f5a Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sun, 18 Jan 2026 02:20:59 +0700 Subject: [PATCH 1/4] Fix active peer notification in background logic --- .../java/com/bitchat/android/mesh/BluetoothMeshService.kt | 8 ++++++++ .../java/com/bitchat/android/ui/NotificationManager.kt | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt index 474c04a5..86a24bd3 100644 --- a/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt +++ b/app/src/main/java/com/bitchat/android/mesh/BluetoothMeshService.kt @@ -178,6 +178,14 @@ class BluetoothMeshService(private val context: Context) { try { com.bitchat.android.services.AppStateStore.setPeers(peerIDs) } catch (_: Exception) { } // Then notify UI delegate if attached delegate?.didUpdatePeerList(peerIDs) + + // If UI is detached (background), update notification manager directly + if (delegate == null) { + try { + serviceNotificationManager.setAppBackgroundState(true) + serviceNotificationManager.showActiveUserNotification(peerIDs) + } catch (_: Exception) { } + } } override fun onPeerRemoved(peerID: String) { try { gossipSyncManager.removeAnnouncementForPeer(peerID) } catch (_: Exception) { } diff --git a/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt b/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt index 9eb72b48..f905c61b 100644 --- a/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt +++ b/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt @@ -174,6 +174,11 @@ class NotificationManager( } fun showActiveUserNotification(peers: List) { + if (peers.isEmpty()) { + notificationIntervalManager.recentlySeenPeers.clear() + return + } + val currentTime = System.currentTimeMillis() val activePeerNotificationIntervalExceeded = (currentTime - notificationIntervalManager.lastNetworkNotificationTime) > ACTIVE_PEERS_NOTIFICATION_TIME_INTERVAL From d773f86655e6960f89d7f1b77f03d9f7ffb6854e Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sun, 18 Jan 2026 02:50:15 +0700 Subject: [PATCH 2/4] Update notification priorities to MAX (Heads-up) for DMs and Active Peers --- .../main/java/com/bitchat/android/ui/NotificationManager.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt b/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt index f905c61b..2d64cf99 100644 --- a/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt +++ b/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt @@ -241,7 +241,7 @@ class NotificationManager( .setContentText(contentText) .setContentIntent(pendingIntent) .setAutoCancel(true) - .setPriority(NotificationCompat.PRIORITY_HIGH) + .setPriority(NotificationCompat.PRIORITY_MAX) .setCategory(NotificationCompat.CATEGORY_MESSAGE) .addPerson(person) .setShowWhen(true) @@ -343,7 +343,7 @@ class NotificationManager( .setContentText(contentText) .setContentIntent(pendingIntent) .setAutoCancel(true) - .setPriority(NotificationCompat.PRIORITY_MIN) + .setPriority(NotificationCompat.PRIORITY_MAX) .setCategory(NotificationCompat.CATEGORY_MESSAGE) .setShowWhen(true) .setWhen(System.currentTimeMillis()) From 85a7a77286c9e29b46ac4265001f7afd9163b389 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sun, 18 Jan 2026 03:15:11 +0700 Subject: [PATCH 3/4] dynamically update notification --- .../bitchat/android/ui/NotificationManager.kt | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt b/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt index 2d64cf99..cb98c1df 100644 --- a/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt +++ b/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt @@ -176,21 +176,27 @@ class NotificationManager( fun showActiveUserNotification(peers: List) { if (peers.isEmpty()) { notificationIntervalManager.recentlySeenPeers.clear() + notificationManager.cancel(ACTIVE_PEERS_NOTIFICATION_ID) return } val currentTime = System.currentTimeMillis() - val activePeerNotificationIntervalExceeded = - (currentTime - notificationIntervalManager.lastNetworkNotificationTime) > ACTIVE_PEERS_NOTIFICATION_TIME_INTERVAL + val timeSinceLast = currentTime - notificationIntervalManager.lastNetworkNotificationTime + val activePeerNotificationIntervalExceeded = timeSinceLast > ACTIVE_PEERS_NOTIFICATION_TIME_INTERVAL val newPeers = peers - notificationIntervalManager.recentlySeenPeers - if (isAppInBackground && activePeerNotificationIntervalExceeded && newPeers.isNotEmpty()) { - Log.d(TAG, "Showing notification for active peers") - showNotificationForActivePeers(peers.size) - notificationIntervalManager.setLastNetworkNotificationTime(currentTime) - notificationIntervalManager.recentlySeenPeers.addAll(newPeers) - } else { - Log.d(TAG, "Skipping notification - app in foreground or it has been less than 5 minutes since last active peer notification") - return + + if (isAppInBackground) { + if (activePeerNotificationIntervalExceeded && newPeers.isNotEmpty()) { + Log.d(TAG, "Showing NEW notification for active peers") + showNotificationForActivePeers(peers.size, onlyAlertOnce = false) + notificationIntervalManager.setLastNetworkNotificationTime(currentTime) + notificationIntervalManager.recentlySeenPeers.addAll(newPeers) + } else if (timeSinceLast <= ACTIVE_PEERS_NOTIFICATION_TIME_INTERVAL) { + // Update existing notification silently to reflect live count + Log.d(TAG, "Updating active peers count silently") + showNotificationForActivePeers(peers.size, onlyAlertOnce = true) + notificationIntervalManager.recentlySeenPeers.addAll(newPeers) + } } } @@ -316,7 +322,7 @@ class NotificationManager( notificationManager.notify((System.currentTimeMillis() and 0x7FFFFFFF).toInt(), builder.build()) } - private fun showNotificationForActivePeers(peersSize: Int) { + private fun showNotificationForActivePeers(peersSize: Int, onlyAlertOnce: Boolean) { // Create intent to open the app val intent = Intent(context, MainActivity::class.java).apply { flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP @@ -346,10 +352,11 @@ class NotificationManager( .setPriority(NotificationCompat.PRIORITY_MAX) .setCategory(NotificationCompat.CATEGORY_MESSAGE) .setShowWhen(true) + .setOnlyAlertOnce(onlyAlertOnce) .setWhen(System.currentTimeMillis()) notificationManager.notify(ACTIVE_PEERS_NOTIFICATION_ID, builder.build()) - Log.d(TAG, "Displayed notification for $contentTitle with ID $ACTIVE_PEERS_NOTIFICATION_ID") + Log.d(TAG, "Displayed notification for $contentTitle with ID $ACTIVE_PEERS_NOTIFICATION_ID (onlyAlertOnce=$onlyAlertOnce)") } private fun showSummaryNotification() { if (pendingNotifications.isEmpty()) return From 9d1649fc693e729b5465a2b32053c8f8e6a24060 Mon Sep 17 00:00:00 2001 From: callebtc <93376500+callebtc@users.noreply.github.com> Date: Sun, 18 Jan 2026 03:24:31 +0700 Subject: [PATCH 4/4] Fix active peer notification live updates and background handling --- .../bitchat/android/ui/NotificationManager.kt | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt b/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt index cb98c1df..c9e40b90 100644 --- a/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt +++ b/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt @@ -183,21 +183,42 @@ class NotificationManager( val currentTime = System.currentTimeMillis() val timeSinceLast = currentTime - notificationIntervalManager.lastNetworkNotificationTime val activePeerNotificationIntervalExceeded = timeSinceLast > ACTIVE_PEERS_NOTIFICATION_TIME_INTERVAL - val newPeers = peers - notificationIntervalManager.recentlySeenPeers + + val isFreshStart = notificationIntervalManager.recentlySeenPeers.isEmpty() - if (isAppInBackground) { - if (activePeerNotificationIntervalExceeded && newPeers.isNotEmpty()) { - Log.d(TAG, "Showing NEW notification for active peers") - showNotificationForActivePeers(peers.size, onlyAlertOnce = false) - notificationIntervalManager.setLastNetworkNotificationTime(currentTime) - notificationIntervalManager.recentlySeenPeers.addAll(newPeers) - } else if (timeSinceLast <= ACTIVE_PEERS_NOTIFICATION_TIME_INTERVAL) { - // Update existing notification silently to reflect live count - Log.d(TAG, "Updating active peers count silently") - showNotificationForActivePeers(peers.size, onlyAlertOnce = true) - notificationIntervalManager.recentlySeenPeers.addAll(newPeers) - } + // Check if we should alert (Heads-up / Sound) + // Only alert if we are in Background AND (it's a fresh start OR enough time passed) + val shouldAlert = isAppInBackground && (isFreshStart || activePeerNotificationIntervalExceeded) + + // Check if we should update an existing notification (Silent) + // If alerting, we definitely update. + // If not alerting: + // - If Background: Update silently (create or update). + // - If Foreground: Update silently ONLY IF notification is already active (don't create new banner over UI). + var shouldUpdate = shouldAlert || isAppInBackground + + if (!shouldUpdate && !isAppInBackground && Build.VERSION.SDK_INT >= 23) { + // Check if the notification is currently active + shouldUpdate = systemNotificationManager.activeNotifications.any { it.id == ACTIVE_PEERS_NOTIFICATION_ID } } + + if (shouldUpdate) { + // If we are alerting, use onlyAlertOnce = false (Sound/Vib). + // If we are just updating/silently posting, use onlyAlertOnce = true. + val onlyAlertOnce = !shouldAlert + + if (shouldAlert) { + Log.d(TAG, "Showing NEW notification for active peers (Heads-up)") + notificationIntervalManager.setLastNetworkNotificationTime(currentTime) + } else { + Log.d(TAG, "Updating active peers notification silently (inBackground=$isAppInBackground)") + } + + showNotificationForActivePeers(peers.size, onlyAlertOnce = onlyAlertOnce) + } + + // Always update tracking + notificationIntervalManager.recentlySeenPeers.addAll(peers) } private fun showNotificationForSender(senderPeerID: String) {