Release 3.8.2.1: reliability, UI probe/logs, CI, signing gates.
Clear sysproxy on core death; probe+reconnect; subscription prune; Best ignores soft UDP; Windows tray; Android protocol gate; CI workflows. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+4
-4
@@ -1,8 +1,8 @@
|
||||
# Navis Android
|
||||
|
||||
Клиент с UI как на Windows 2.2: список нод, пинг, «лучший», автоподключение, подписка.
|
||||
Клиент с UI как на Desktop: список нод, пинг, «лучший», автоподключение, подписка.
|
||||
|
||||
Версия APK: **2.3.0**
|
||||
Версия APK: **3.8.2+1** (синхронизируется с Desktop через `scripts/sync-version.py`).
|
||||
|
||||
## Протоколы
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|----------|--------------|
|
||||
| VLESS / VMess / Trojan (Xray) | SOCKS core + VpnService |
|
||||
| Hysteria 2 | SOCKS core + VpnService |
|
||||
| NaiveProxy | импорт в UI; Android Chromium-бинарник не бандлится |
|
||||
| AmneziaWG | импорт в UI; полный Tun — следующий релиз |
|
||||
| NaiveProxy | импорт в UI; подключение отключено (только Desktop) |
|
||||
| AmneziaWG | импорт в UI; подключение отключено (только Desktop) |
|
||||
|
||||
## Сборка
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ android {
|
||||
minSdk = 26
|
||||
targetSdk = 35
|
||||
// versionCode = major*1_000_000 + minor*10_000 + patch*100 + build
|
||||
versionCode = 2_070_201
|
||||
versionName = "2.7.3+1"
|
||||
versionCode = 3080201
|
||||
versionName = "3.8.2+1"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
ndk {
|
||||
abiFilters += listOf("arm64-v8a", "armeabi-v7a", "x86_64")
|
||||
|
||||
@@ -24,6 +24,12 @@ enum class Proto(val label: String) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Desktop has Naive/AWG; this APK only runs Xray + Hysteria2 in VpnService. */
|
||||
fun supportedOnAndroid(): Boolean = when (this) {
|
||||
VLESS, VMESS, TROJAN, HYSTERIA2 -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
data class Profile(
|
||||
|
||||
@@ -59,6 +59,10 @@ class MainActivity : ComponentActivity() {
|
||||
vm.setMeta("Выберите сервер", true)
|
||||
return
|
||||
}
|
||||
if (!p.protocol.supportedOnAndroid()) {
|
||||
vm.setMeta("${p.protocol.label}: на Android недоступен — используйте VLESS/VMess/Trojan/Hy2", true)
|
||||
return
|
||||
}
|
||||
prepareVpnThen {
|
||||
startService(
|
||||
Intent(this, NavisVpnService::class.java)
|
||||
|
||||
@@ -139,12 +139,18 @@ class MainViewModel(app: Application) : AndroidViewModel(app) {
|
||||
}
|
||||
val rows = store.pingAll(profiles)
|
||||
_state.update { it.copy(pings = rows.associateBy { r -> r.id }) }
|
||||
val best = store.bestOf(rows) ?: run {
|
||||
setMeta("нет доступных серверов", true)
|
||||
val supported = profiles.filter { it.protocol.supportedOnAndroid() }
|
||||
val supportedRows = rows.filter { r -> supported.any { it.id == r.id } }
|
||||
val best = store.bestOf(supportedRows) ?: run {
|
||||
setMeta("нет доступных серверов (Android: VLESS/VMess/Trojan/Hy2)", true)
|
||||
return
|
||||
}
|
||||
store.setActiveId(best.id)
|
||||
val profile = profiles.first { it.id == best.id }
|
||||
if (!profile.protocol.supportedOnAndroid()) {
|
||||
setMeta("${profile.protocol.label}: на Android недоступен", true)
|
||||
return
|
||||
}
|
||||
_state.update { it.copy(activeId = best.id) }
|
||||
setMeta("Лучший: ${profile.name} · ${best.ms} ms")
|
||||
if (connect && prepare != null) {
|
||||
|
||||
@@ -100,7 +100,7 @@ fun NavisScreen(
|
||||
Text("2.6.1", Modifier.padding(horizontal = 8.dp, vertical = 2.dp), fontSize = 12.sp, fontWeight = FontWeight.Bold, color = AccentDeep)
|
||||
}
|
||||
}
|
||||
Text("Android · Naive · Hy2 · AWG · Xray", color = Muted, fontSize = 13.sp)
|
||||
Text("Android · Xray · Hy2 (Naive/AWG — только Desktop)", color = Muted, fontSize = 13.sp)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
|
||||
Surface(shape = RoundedCornerShape(22.dp), color = Color.White.copy(alpha = 0.85f), tonalElevation = 2.dp) {
|
||||
|
||||
Reference in New Issue
Block a user