feat: Enhance FCM token management by adding unsubscribe logic to prevent duplicate registrations
This commit is contained in:
@@ -6,6 +6,7 @@ import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.google.firebase.messaging.FirebaseMessagingService
|
||||
import com.google.firebase.messaging.RemoteMessage
|
||||
@@ -41,6 +42,11 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() {
|
||||
// 🔥 Флаг - приложение в foreground (видимо пользователю)
|
||||
@Volatile var isAppInForeground = false
|
||||
|
||||
// Dedup: suppress duplicate pushes from the server within a short window.
|
||||
// Key = senderPublicKey (or "__simple__"), Value = timestamp of last shown notification.
|
||||
private const val DEDUP_WINDOW_MS = 10_000L
|
||||
private val lastNotifTimestamps = java.util.concurrent.ConcurrentHashMap<String, Long>()
|
||||
|
||||
/** Уникальный notification ID для каждого чата (по publicKey) */
|
||||
fun getNotificationIdForChat(senderPublicKey: String): Int {
|
||||
return senderPublicKey.hashCode() and 0x7FFFFFFF // positive int
|
||||
@@ -77,6 +83,7 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() {
|
||||
/** Вызывается когда получено push-уведомление */
|
||||
override fun onMessageReceived(remoteMessage: RemoteMessage) {
|
||||
super.onMessageReceived(remoteMessage)
|
||||
Log.d(TAG, "\u2709\ufe0f onMessageReceived: messageId=${remoteMessage.messageId} from=${remoteMessage.from} data=${remoteMessage.data} notif=${remoteMessage.notification?.body}")
|
||||
|
||||
var handledMessageData = false
|
||||
|
||||
@@ -147,6 +154,16 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() {
|
||||
if (isAppInForeground || !areNotificationsEnabled()) {
|
||||
return
|
||||
}
|
||||
// Dedup: suppress duplicate pushes from the same sender within DEDUP_WINDOW_MS
|
||||
val dedupKey = senderPublicKey?.trim().orEmpty().ifEmpty { "__no_sender__" }
|
||||
val now = System.currentTimeMillis()
|
||||
val lastTs = lastNotifTimestamps[dedupKey]
|
||||
if (lastTs != null && now - lastTs < DEDUP_WINDOW_MS) {
|
||||
Log.d(TAG, "\ud83d\udeab Dedup BLOCKED notification for key=$dedupKey, delta=${now - lastTs}ms")
|
||||
return // duplicate push — skip
|
||||
}
|
||||
lastNotifTimestamps[dedupKey] = now
|
||||
Log.d(TAG, "\u2705 Showing notification for key=$dedupKey")
|
||||
// Desktop parity: suppress notifications during sync (useDialogFiber.ts checks
|
||||
// protocolState != ProtocolState.SYNCHRONIZATION before calling notify()).
|
||||
if (ProtocolManager.syncInProgress.value) {
|
||||
@@ -198,9 +215,20 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() {
|
||||
if (isAppInForeground || !areNotificationsEnabled()) {
|
||||
return
|
||||
}
|
||||
// Dedup: suppress duplicate pushes within DEDUP_WINDOW_MS
|
||||
val dedupKey = "__simple__"
|
||||
val now = System.currentTimeMillis()
|
||||
val lastTs = lastNotifTimestamps[dedupKey]
|
||||
if (lastTs != null && now - lastTs < DEDUP_WINDOW_MS) {
|
||||
return // duplicate push — skip
|
||||
}
|
||||
lastNotifTimestamps[dedupKey] = now
|
||||
|
||||
createNotificationChannel()
|
||||
|
||||
// Deterministic ID — duplicates replace each other instead of stacking
|
||||
val notifId = (title + body).hashCode() and 0x7FFFFFFF
|
||||
|
||||
val intent =
|
||||
Intent(this, MainActivity::class.java).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
@@ -209,7 +237,7 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() {
|
||||
val pendingIntent =
|
||||
PendingIntent.getActivity(
|
||||
this,
|
||||
0,
|
||||
notifId,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||
)
|
||||
@@ -226,7 +254,7 @@ class RosettaFirebaseMessagingService : FirebaseMessagingService() {
|
||||
|
||||
val notificationManager =
|
||||
getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
notificationManager.notify(System.currentTimeMillis().toInt(), notification)
|
||||
notificationManager.notify(notifId, notification)
|
||||
}
|
||||
|
||||
/** Создать notification channel для Android 8+ */
|
||||
|
||||
Reference in New Issue
Block a user