diff --git a/android/src/main/java/app/tauri/notification/NotificationPlugin.kt b/android/src/main/java/app/tauri/notification/NotificationPlugin.kt index a34ac8e..675a79e 100644 --- a/android/src/main/java/app/tauri/notification/NotificationPlugin.kt +++ b/android/src/main/java/app/tauri/notification/NotificationPlugin.kt @@ -24,7 +24,6 @@ import app.tauri.plugin.Plugin import com.google.firebase.messaging.FirebaseMessaging import org.unifiedpush.android.connector.UnifiedPush import java.util.ArrayDeque -import java.util.UUID const val LOCAL_NOTIFICATIONS = "permissionState" private const val MAX_PENDING_ACTIONS = 32 @@ -477,7 +476,7 @@ class NotificationPlugin(private val activity: Activity): Plugin(activity) { pendingPushRegistration = PushRegistration( requestedVapid, provider, - if (provider == "fcm") null else "sable-registration-${UUID.randomUUID()}", + if (provider == "fcm") null else unifiedPushState.instanceForRegistration(), distributor, PushRegistrationPhase.PERMISSION, invoke, @@ -579,7 +578,7 @@ class NotificationPlugin(private val activity: Activity): Plugin(activity) { val pendingUnifiedPush = pendingPushRegistration?.takeIf { it.phase == PushRegistrationPhase.UNIFIED_PUSH || it.phase == PushRegistrationPhase.DISTRIBUTOR } - val instanceToUnregister = pendingUnifiedPush?.instance ?: unifiedPushState.activeInstance + val instanceToUnregister = pendingUnifiedPush?.instance ?: unifiedPushState.activeInstance ?: UnifiedPushStateStore.INSTANCE finishPushRegistrationError("Push registration cancelled by unregister") if (pendingUnifiedPush != null || unifiedPushState.activeProvider == "unifiedpush") { @@ -641,14 +640,16 @@ class NotificationPlugin(private val activity: Activity): Plugin(activity) { invoke.reject("Cannot change distributor while push registration is in progress") return } - if (UnifiedPush.getSavedDistributor(activity) != distributor) { - try { retireUnifiedPush(unifiedPushState.activeInstance) } catch (error: Exception) { + val distributorChanged = UnifiedPush.getSavedDistributor(activity) != distributor + if (distributorChanged) { + try { retireUnifiedPush(unifiedPushState.activeInstance ?: UnifiedPushStateStore.INSTANCE) } catch (error: Exception) { invoke.reject(error.message ?: "Failed to retire UnifiedPush registration") return } if (unifiedPushState.activeProvider == "unifiedpush") unifiedPushState.activeProvider = null } UnifiedPush.saveDistributor(activity, distributor) + if (distributorChanged) unifiedPushState.ensureExplicitInstance() invoke.resolve() } @@ -664,6 +665,7 @@ class NotificationPlugin(private val activity: Activity): Plugin(activity) { return } unifiedPushState.setUnifiedPushActive() + unifiedPushState.endpoint = endpoint unifiedPushState.activeInstance = registration.instance val result = JSObject() result.put("deviceToken", endpoint) @@ -782,6 +784,14 @@ class NotificationPlugin(private val activity: Activity): Plugin(activity) { unifiedPushGeneration++ try { UnifiedPush.unregister(activity, instance ?: UnifiedPushStateStore.INSTANCE) } catch (_: Exception) { } + val activeInstance = unifiedPushState.activeInstance + val retiresActiveInstance = activeInstance == instance || + (activeInstance == null && instance == UnifiedPushStateStore.INSTANCE && + unifiedPushState.activeProvider == "unifiedpush") + if (retiresActiveInstance) { + if (unifiedPushState.activeProvider == "unifiedpush") unifiedPushState.activeProvider = null + unifiedPushState.clearRegistration() + } } // Called by TauriFirebaseMessagingService when a new token is received diff --git a/android/src/main/java/app/tauri/notification/UnifiedPushStateStore.kt b/android/src/main/java/app/tauri/notification/UnifiedPushStateStore.kt index 28e7b7c..f8e2daa 100644 --- a/android/src/main/java/app/tauri/notification/UnifiedPushStateStore.kt +++ b/android/src/main/java/app/tauri/notification/UnifiedPushStateStore.kt @@ -2,6 +2,7 @@ package app.tauri.notification import android.content.Context import org.unifiedpush.android.connector.UnifiedPush +import java.util.UUID internal class UnifiedPushStateStore(private val context: Context) { private val prefs = context.getSharedPreferences("tauri-notifications", Context.MODE_PRIVATE) @@ -11,8 +12,26 @@ internal class UnifiedPushStateStore(private val context: Context) { ?: if (!prefs.contains("push-provider") && UnifiedPush.getSavedDistributor(context) != null) "unifiedpush" else null set(value) = prefs.edit().putString("push-provider", value ?: "none").apply() var activeInstance: String? - get() = prefs.getString("push-instance", null) ?: INSTANCE + get() = prefs.getString("push-instance", null) + ?: if (activeProvider == "unifiedpush") INSTANCE else null set(value) = prefs.edit().putString("push-instance", value ?: INSTANCE).apply() + var endpoint: String? + get() = prefs.getString("up-endpoint", null) + set(value) = prefs.edit().putString("up-endpoint", value).apply() + + fun clearRegistration() { + prefs.edit().remove("push-instance").remove("up-endpoint").apply() + } + fun instanceForRegistration(): String { + activeInstance?.let { return it } + if (activeProvider == "unifiedpush") return INSTANCE + return UUID.randomUUID().toString().also { activeInstance = it } + } + fun ensureExplicitInstance() { + if (prefs.getString("push-instance", null) == null) { + activeInstance = UUID.randomUUID().toString() + } + } fun setUnifiedPushActive() { activeProvider = "unifiedpush" } companion object {