Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff8c5361cb |
@@ -74,6 +74,8 @@ class AgentStatusFragment : Fragment() {
|
||||
private lateinit var mediaPermissionDetail: TextView
|
||||
private lateinit var mediaPermissionAction: android.widget.Button
|
||||
private lateinit var deviceText: TextView
|
||||
private lateinit var deviceWifiText: TextView
|
||||
private lateinit var deviceDebugText: TextView
|
||||
private val mediaPermissionRequestLauncher by lazy {
|
||||
registerForActivityResult(androidx.activity.result.contract.ActivityResultContracts.RequestPermission()) {
|
||||
refreshStatus()
|
||||
@@ -168,6 +170,20 @@ class AgentStatusFragment : Fragment() {
|
||||
}
|
||||
addView(mediaPermissionAction)
|
||||
}))
|
||||
addView(context.card(context.cardColumn().apply {
|
||||
addView(context.label("设备连接", 14f, context.getColor(R.color.agent_text_muted)))
|
||||
deviceWifiText = context.label("Wi-Fi IP:—", 18f, context.getColor(R.color.agent_text), true).apply {
|
||||
setPadding(0, context.dp(6), 0, 0)
|
||||
}
|
||||
deviceDebugText = context.label("无线调试:—", 18f, context.getColor(R.color.agent_text_muted), true).apply {
|
||||
setPadding(0, context.dp(6), 0, 0)
|
||||
}
|
||||
addView(deviceWifiText)
|
||||
addView(deviceDebugText)
|
||||
addView(context.label(DeviceConnectionPolicy.PORT_HINT, 14f, context.getColor(R.color.agent_text_muted)).apply {
|
||||
setPadding(0, context.dp(6), 0, 0)
|
||||
})
|
||||
}))
|
||||
}
|
||||
refreshLayout = SwipeRefreshLayout(context).apply {
|
||||
setColorSchemeResources(R.color.agent_primary_light)
|
||||
@@ -245,6 +261,10 @@ class AgentStatusFragment : Fragment() {
|
||||
private fun refreshStatus() {
|
||||
if (!isAdded || view == null) return
|
||||
val context = requireContext()
|
||||
val deviceConnection = DeviceConnectionPolicy.display(DeviceConnectionReader.read(context))
|
||||
deviceWifiText.text = deviceConnection.wifiText
|
||||
deviceDebugText.text = deviceConnection.debugText
|
||||
deviceDebugText.setTextColor(context.getColor(deviceConnection.debugColor))
|
||||
val state = stateStore.read()
|
||||
val connected = state.code in setOf("ONLINE", "BUSY", "COLLECTION_COOLDOWN")
|
||||
connectionTitle.text = when (state.code) {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package cn.ilapage.goauto.agent.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.NetworkCapabilities
|
||||
import android.provider.Settings
|
||||
import androidx.annotation.ColorRes
|
||||
import cn.ilapage.goauto.agent.R
|
||||
import java.net.Inet4Address
|
||||
import java.net.InetAddress
|
||||
|
||||
/** 无线调试开关的读取结果;读取失败为 [UNKNOWN]。 */
|
||||
internal enum class WirelessDebugState { ENABLED, DISABLED, UNKNOWN }
|
||||
|
||||
internal data class DeviceConnectionReading(
|
||||
val wifiIpv4: String?,
|
||||
val wirelessDebug: WirelessDebugState,
|
||||
)
|
||||
|
||||
internal data class DeviceConnectionDisplay(
|
||||
val wifiText: String,
|
||||
val debugText: String,
|
||||
@ColorRes val debugColor: Int,
|
||||
)
|
||||
|
||||
/** 原始读数到显示文案/颜色的纯函数策略,不依赖 Android 系统服务。 */
|
||||
internal object DeviceConnectionPolicy {
|
||||
const val PORT_HINT = "端口请在 开发者选项 → 无线调试 中查看"
|
||||
const val NO_WIFI_TEXT = "未连接 Wi-Fi"
|
||||
|
||||
/** 仅当前网络为 Wi-Fi 时,从地址列表中取第一个非回环 IPv4;否则返回 null。 */
|
||||
fun selectWifiIpv4(isWifi: Boolean, addresses: List<InetAddress>): String? {
|
||||
if (!isWifi) return null
|
||||
return addresses.firstOrNull { it is Inet4Address && !it.isLoopbackAddress }?.hostAddress
|
||||
}
|
||||
|
||||
/** adb_wifi_enabled 原始值:1 开启,0 未开启,其他值或读取失败(null)为未知。 */
|
||||
fun debugState(raw: Int?): WirelessDebugState = when (raw) {
|
||||
1 -> WirelessDebugState.ENABLED
|
||||
0 -> WirelessDebugState.DISABLED
|
||||
else -> WirelessDebugState.UNKNOWN
|
||||
}
|
||||
|
||||
fun display(reading: DeviceConnectionReading): DeviceConnectionDisplay {
|
||||
val (text, color) = when (reading.wirelessDebug) {
|
||||
WirelessDebugState.ENABLED -> "已开启" to R.color.agent_primary_light
|
||||
WirelessDebugState.DISABLED -> "未开启" to R.color.agent_warning
|
||||
WirelessDebugState.UNKNOWN -> "无法读取" to R.color.agent_text_muted
|
||||
}
|
||||
return DeviceConnectionDisplay(
|
||||
wifiText = "Wi-Fi IP:${reading.wifiIpv4 ?: NO_WIFI_TEXT}",
|
||||
debugText = "无线调试:$text",
|
||||
debugColor = color,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** 系统读取的薄封装;任何异常都降级为「未知」,不记录日志、不持久化。 */
|
||||
internal object DeviceConnectionReader {
|
||||
fun read(context: Context): DeviceConnectionReading = DeviceConnectionReading(
|
||||
wifiIpv4 = readWifiIpv4(context),
|
||||
wirelessDebug = DeviceConnectionPolicy.debugState(readDebugRaw(context)),
|
||||
)
|
||||
|
||||
private fun readWifiIpv4(context: Context): String? = try {
|
||||
val manager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
|
||||
val network = manager?.activeNetwork
|
||||
val isWifi = network?.let { manager.getNetworkCapabilities(it) }
|
||||
?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) == true
|
||||
val addresses = if (isWifi && manager != null && network != null) {
|
||||
manager.getLinkProperties(network)?.linkAddresses?.map { it.address }.orEmpty()
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
DeviceConnectionPolicy.selectWifiIpv4(isWifi, addresses)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
private fun readDebugRaw(context: Context): Int? = try {
|
||||
Settings.Global.getInt(context.contentResolver, "adb_wifi_enabled", 0)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package cn.ilapage.goauto.agent
|
||||
|
||||
import cn.ilapage.goauto.agent.ui.DeviceConnectionPolicy
|
||||
import cn.ilapage.goauto.agent.ui.DeviceConnectionReading
|
||||
import cn.ilapage.goauto.agent.ui.WirelessDebugState
|
||||
import java.net.InetAddress
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Test
|
||||
|
||||
class DeviceConnectionPolicyTest {
|
||||
private fun ip(text: String) = InetAddress.getByName(text)
|
||||
|
||||
@Test fun wifiWithIpv4ReturnsAddress() {
|
||||
assertEquals("192.168.0.93", DeviceConnectionPolicy.selectWifiIpv4(true, listOf(ip("192.168.0.93"))))
|
||||
}
|
||||
|
||||
@Test fun nonWifiReturnsNull() {
|
||||
assertNull(DeviceConnectionPolicy.selectWifiIpv4(false, listOf(ip("10.0.0.2"))))
|
||||
}
|
||||
|
||||
@Test fun wifiWithOnlyIpv6ReturnsNull() {
|
||||
assertNull(DeviceConnectionPolicy.selectWifiIpv4(true, listOf(ip("2001:db8::1"))))
|
||||
}
|
||||
|
||||
@Test fun wifiWithMultipleAddressesPicksIpv4() {
|
||||
assertEquals(
|
||||
"172.16.1.5",
|
||||
DeviceConnectionPolicy.selectWifiIpv4(true, listOf(ip("2001:db8::1"), ip("172.16.1.5"))),
|
||||
)
|
||||
}
|
||||
|
||||
@Test fun loopbackIpv4IsSkipped() {
|
||||
assertNull(DeviceConnectionPolicy.selectWifiIpv4(true, listOf(ip("127.0.0.1"))))
|
||||
}
|
||||
|
||||
@Test fun debugRawValuesMapToState() {
|
||||
assertEquals(WirelessDebugState.ENABLED, DeviceConnectionPolicy.debugState(1))
|
||||
assertEquals(WirelessDebugState.DISABLED, DeviceConnectionPolicy.debugState(0))
|
||||
assertEquals(WirelessDebugState.UNKNOWN, DeviceConnectionPolicy.debugState(2))
|
||||
assertEquals(WirelessDebugState.UNKNOWN, DeviceConnectionPolicy.debugState(null))
|
||||
}
|
||||
|
||||
@Test fun displayEnabledUsesPrimaryColor() {
|
||||
val d = DeviceConnectionPolicy.display(DeviceConnectionReading("192.168.0.93", WirelessDebugState.ENABLED))
|
||||
assertEquals("Wi-Fi IP:192.168.0.93", d.wifiText)
|
||||
assertEquals("无线调试:已开启", d.debugText)
|
||||
assertEquals(R.color.agent_primary_light, d.debugColor)
|
||||
}
|
||||
|
||||
@Test fun displayDisabledUsesWarningColorAndNoWifiText() {
|
||||
val d = DeviceConnectionPolicy.display(DeviceConnectionReading(null, WirelessDebugState.DISABLED))
|
||||
assertEquals("Wi-Fi IP:未连接 Wi-Fi", d.wifiText)
|
||||
assertEquals("无线调试:未开启", d.debugText)
|
||||
assertEquals(R.color.agent_warning, d.debugColor)
|
||||
}
|
||||
|
||||
@Test fun displayUnknownUsesMutedColor() {
|
||||
val d = DeviceConnectionPolicy.display(DeviceConnectionReading(null, WirelessDebugState.UNKNOWN))
|
||||
assertEquals("无线调试:无法读取", d.debugText)
|
||||
assertEquals(R.color.agent_text_muted, d.debugColor)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user