From 491cbcb25911f9d5506f8cbdc59668f11a875dc2 Mon Sep 17 00:00:00 2001 From: ericek111 Date: Fri, 25 Sep 2026 18:31:50 +0000 Subject: [PATCH] Leave the server when the app is swiped away The process lived on without a screen, or was killed without a word, and the server held our identity as a ghost until it timed out, refusing a reconnect in the meantime as a clone. Co-Authored-By: Claude Opus 5.5 --- .../java/com/ts3client/android/ConnectionService.kt | 13 +++++++++++++ .../java/com/ts3client/android/SessionController.kt | 6 ++++++ 2 files changed, 19 insertions(+) diff --git a/android/app/src/main/java/com/ts3client/android/ConnectionService.kt b/android/app/src/main/java/com/ts3client/android/ConnectionService.kt index c68e27d..9a46042 100644 --- a/android/app/src/main/java/com/ts3client/android/ConnectionService.kt +++ b/android/app/src/main/java/com/ts3client/android/ConnectionService.kt @@ -12,6 +12,7 @@ import android.net.wifi.WifiManager import android.os.PowerManager import androidx.lifecycle.LifecycleService import androidx.lifecycle.lifecycleScope +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @@ -66,6 +67,18 @@ class ConnectionService : LifecycleService() { return START_NOT_STICKY } + /** + * The user swiped the app away: they are done with it, connection included. Leaving + * properly spares the server a ghost that would hold our identity until it times out. + */ + override fun onTaskRemoved(rootIntent: Intent?) { + super.onTaskRemoved(rootIntent) + lifecycleScope.launch(Dispatchers.IO) { + sessions.leave() + stopSelf() + } + } + override fun onDestroy() { wifiLock.release() wakeLock.release() diff --git a/android/app/src/main/java/com/ts3client/android/SessionController.kt b/android/app/src/main/java/com/ts3client/android/SessionController.kt index 7b5521f..af77253 100644 --- a/android/app/src/main/java/com/ts3client/android/SessionController.kt +++ b/android/app/src/main/java/com/ts3client/android/SessionController.kt @@ -162,6 +162,12 @@ class SessionController(private val context: Context) { session.disconnect() } + /** Leaves the server before returning, for when the app goes away with the connection. */ + fun leave() { + network.leaving() + session.shutdown() + } + // ---- bookmarks ---- fun addBookmark(label: String, address: String, nickname: String, password: String) {