diff --git a/Android/app/build.gradle.kts b/Android/app/build.gradle.kts index b3a56fb4..2b011839 100644 --- a/Android/app/build.gradle.kts +++ b/Android/app/build.gradle.kts @@ -11,8 +11,8 @@ android { applicationId = "com.archipelago.app" minSdk = 26 targetSdk = 35 - versionCode = 21 - versionName = "0.5.1" + versionCode = 22 + versionName = "0.5.2" vectorDrawables { useSupportLibrary = true diff --git a/Android/app/src/main/java/com/archipelago/app/fips/ArchyVpnService.kt b/Android/app/src/main/java/com/archipelago/app/fips/ArchyVpnService.kt index 46811691..36714e05 100644 --- a/Android/app/src/main/java/com/archipelago/app/fips/ArchyVpnService.kt +++ b/Android/app/src/main/java/com/archipelago/app/fips/ArchyVpnService.kt @@ -61,6 +61,13 @@ class ArchyVpnService : VpnService() { .setMtu(1280) .addAddress(identity.address, 128) .addRoute("fd00::", 8) + // The TUN is IPv6-only. Android blocks every address family + // the VPN has no address for — without this, bringing the + // mesh up cut ALL of the phone's IPv4 internet. + .allowFamily(android.system.OsConstants.AF_INET) + // And let apps that bind their own network skip the TUN + // entirely — this is mesh reachability, not a privacy VPN. + .allowBypass() .establish() } catch (e: Exception) { Log.e(TAG, "VPN establish failed", e) diff --git a/Android/app/src/main/java/com/archipelago/app/ui/screens/ServerConnectScreen.kt b/Android/app/src/main/java/com/archipelago/app/ui/screens/ServerConnectScreen.kt index d04f4104..4944fdda 100644 --- a/Android/app/src/main/java/com/archipelago/app/ui/screens/ServerConnectScreen.kt +++ b/Android/app/src/main/java/com/archipelago/app/ui/screens/ServerConnectScreen.kt @@ -85,6 +85,7 @@ import com.archipelago.app.ui.theme.TextMuted import com.archipelago.app.ui.theme.TextPrimary import com.archipelago.app.ui.theme.TextSecondary import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.net.HttpURLConnection @@ -171,10 +172,29 @@ fun ServerConnectScreen( errorMessage = null scope.launch { - val result = testConnection(server) + var reachable = testConnection(server) + + // LAN address didn't answer — phone off-LAN (5G) or DHCP moved the + // node. The scanned IP was only ever a dial hint; the node's real + // identity is its npub and its ULA is reachable from anywhere over + // the mesh. Bring the tunnel up and probe the ULA before failing. + if (!reachable && server.meshIp.isNotBlank()) { + FipsManager.autoStartIfReady(context) + val meshServer = server.copy( + address = server.meshIp, + useHttps = false, + port = "", + ) + // The tunnel + mesh route need a moment on cold start. + for (attempt in 0 until 4) { + if (attempt > 0) delay(2000) + reachable = testConnection(meshServer) + if (reachable) break + } + } isConnecting = false - if (result) { + if (reachable) { prefs.setActiveServer(server) onConnected(server.toUrl()) } else { diff --git a/docs/HANDOFF-2026-07-23-companion-apk-deploy.md b/docs/HANDOFF-2026-07-23-companion-apk-deploy.md index 5920bbcf..d521f263 100644 --- a/docs/HANDOFF-2026-07-23-companion-apk-deploy.md +++ b/docs/HANDOFF-2026-07-23-companion-apk-deploy.md @@ -18,7 +18,14 @@ user's hands. support; web scan modal hands live scanning to it. - npub-keyed saved servers (pairing contract item 1, PR #106). - Served APK refreshed: `neode-ui/public/packages/archipelago-companion.apk` - is now **0.5.1 / versionCode 21** (this commit). + is now **0.5.2 / versionCode 22**, which additionally fixes the two field + failures from the user's 5G test (screenshots, 21:54): + - **Mesh VPN no longer kills the phone's internet** — the IPv6-only TUN + never called `allowFamily(AF_INET)`, so Android blocked all IPv4 while + the mesh was up. Now allowed (+ `allowBypass`). + - **Off-LAN connect works** — `connect()` no longer hard-fails when the + scanned LAN IP doesn't answer; it brings the mesh up and probes the + node's ULA (`meshIp`) with retries before reporting failure. ## What to do diff --git a/neode-ui/public/packages/archipelago-companion.apk b/neode-ui/public/packages/archipelago-companion.apk index 83c4a299..b4331df4 100644 Binary files a/neode-ui/public/packages/archipelago-companion.apk and b/neode-ui/public/packages/archipelago-companion.apk differ