From 44a0a17f68a6d3e68bd08b7cf426f593c632587b Mon Sep 17 00:00:00 2001 From: Zhengqi Zhang <1548069580@qq.com> Date: Thu, 10 Sep 2026 11:39:34 +0800 Subject: [PATCH] fix(android): avoid duplicate foreground notifications (#2559) --- .../android/app/src/main/AndroidManifest.xml | 6 ++++-- .../easytier/MainForegroundService.kt | 13 ++++++------ .../android/src/main/java/TauriVpnService.kt | 20 +++++++++++++++++++ 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/easytier-gui/src-tauri/gen/android/app/src/main/AndroidManifest.xml b/easytier-gui/src-tauri/gen/android/app/src/main/AndroidManifest.xml index c2a0206d..8dc3b17e 100644 --- a/easytier-gui/src-tauri/gen/android/app/src/main/AndroidManifest.xml +++ b/easytier-gui/src-tauri/gen/android/app/src/main/AndroidManifest.xml @@ -3,7 +3,6 @@ - + = Build.VERSION_CODES.Q) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { startForeground( NOTIFICATION_ID, notification, - ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC + ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE ) } else { startForeground(NOTIFICATION_ID, notification) @@ -52,7 +51,7 @@ class MainForegroundService : Service() { val channel = NotificationChannel( CHANNEL_ID, "easytier notice", - NotificationManager.IMPORTANCE_DEFAULT + NotificationManager.IMPORTANCE_LOW ) val manager = getSystemService(NotificationManager::class.java) manager?.createNotificationChannel(channel) @@ -61,4 +60,4 @@ class MainForegroundService : Service() { } } } -} \ No newline at end of file +} diff --git a/tauri-plugin-vpnservice/android/src/main/java/TauriVpnService.kt b/tauri-plugin-vpnservice/android/src/main/java/TauriVpnService.kt index e1be67bd..d8c1a5d4 100644 --- a/tauri-plugin-vpnservice/android/src/main/java/TauriVpnService.kt +++ b/tauri-plugin-vpnservice/android/src/main/java/TauriVpnService.kt @@ -63,6 +63,7 @@ class TauriVpnService : VpnService() { override fun onDestroy() { println("vpn on destroy") disconnect() + setMainForegroundServiceEnabled(true) stopForeground(STOP_FOREGROUND_REMOVE) self = null EasyTierVpnTileService.requestStateUpdate(this) @@ -72,6 +73,7 @@ class TauriVpnService : VpnService() { override fun onRevoke() { println("vpn on revoke") disconnect() + setMainForegroundServiceEnabled(true) stopForeground(STOP_FOREGROUND_REMOVE) self = null EasyTierVpnTileService.requestStateUpdate(this) @@ -126,6 +128,24 @@ class TauriVpnService : VpnService() { } else { startForeground(NOTIFICATION_ID, notification) } + + // A TUN-backed network is now protected by this foreground service, so the + // no-TUN keepalive service is redundant and would show a second notification. + setMainForegroundServiceEnabled(false) + } + + private fun setMainForegroundServiceEnabled(enabled: Boolean) { + val intent = Intent().setClassName(packageName, "$packageName.MainForegroundService") + if (!enabled) { + stopService(intent) + return + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + startForegroundService(intent) + } else { + startService(intent) + } } private fun createNotificationChannel() {