diff --git a/apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt b/apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt index 269b6bd42212..dd96cd384ea3 100644 --- a/apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt +++ b/apps/android/app/src/main/java/ai/openclaw/app/NodeRuntime.kt @@ -1452,11 +1452,14 @@ class NodeRuntime( } fun refreshGatewayConnection() { - val endpoint = - connectedEndpoint ?: run { - _statusText.value = "Failed: no cached gateway endpoint" - return - } + val endpoint = connectedEndpoint + if (endpoint == null) { + resolvePreferredGatewayEndpoint()?.let(::connect) + ?: run { + _statusText.value = "Failed: no saved gateway endpoint" + } + return + } operatorStatusText = "Connecting…" updateStatus() connectWithAuth(endpoint = endpoint, auth = resolveGatewayConnectAuth(), reconnect = true) diff --git a/apps/android/app/src/test/java/ai/openclaw/app/GatewayBootstrapAuthTest.kt b/apps/android/app/src/test/java/ai/openclaw/app/GatewayBootstrapAuthTest.kt index 4d1ab00c912a..2316d8ddfda7 100644 --- a/apps/android/app/src/test/java/ai/openclaw/app/GatewayBootstrapAuthTest.kt +++ b/apps/android/app/src/test/java/ai/openclaw/app/GatewayBootstrapAuthTest.kt @@ -294,6 +294,38 @@ class GatewayBootstrapAuthTest { assertEquals("aaaaaaaa", prefs.loadGatewayTlsFingerprint(endpoint.stableId)) } + @Test + fun refreshGatewayConnection_reconnectsSavedManualEndpointAfterDisconnect() { + val app = RuntimeEnvironment.getApplication() + val securePrefs = + app.getSharedPreferences( + "openclaw.node.secure.test.${UUID.randomUUID()}", + android.content.Context.MODE_PRIVATE, + ) + val prefs = SecurePrefs(app, securePrefsOverride = securePrefs) + prefs.setManualEnabled(true) + prefs.setManualHost("127.0.0.1") + prefs.setManualPort(18789) + prefs.setManualTls(false) + prefs.setGatewayToken("shared-token") + val runtime = NodeRuntime(app, prefs) + + runtime.connect( + GatewayEndpoint.manual(host = "127.0.0.1", port = 18789), + NodeRuntime.GatewayConnectAuth(token = "initial-token", bootstrapToken = null, password = null), + ) + runtime.disconnect() + assertNull(desiredConnection(runtime, "nodeSession")) + + runtime.refreshGatewayConnection() + + val desired = desiredConnection(runtime, "nodeSession") ?: error("Expected desired node connection") + val endpoint = readField(desired, "endpoint") + assertEquals("127.0.0.1", endpoint.host) + assertEquals(18789, endpoint.port) + assertEquals("shared-token", readField(desired, "token")) + } + @Test fun connect_showsSecureEndpointGuidanceWhenTlsProbeFails() { val app = RuntimeEnvironment.getApplication()