我已经NetworkCallback注册了connectivityManager.registerDefaultNetworkCallback(networkCallback). 手机已打开并连接了 WiFi,但是当我调用它时,它给出了一个我可以找到的 Android SDK 文档中不存在的capabilities.transportInfo!!::class.qualifiedName类名称。android.net.VpnTransportInfo如果设备通过 VPN 连接,如何获取 SSID?为什么文档中没有这个类?
初始化:
private val networkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.build()
init {
//upon register, callback will be called, so no need to initialize
//registerDefaultNetworkCallback does not call back with a WifiInfo when using VPN
//connectivityManager.registerDefaultNetworkCallback(networkCallback)
//should return only WifiInfo as TransportInfo since networkRequest only requests Wifi transport type
connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
}
Run Code Online (Sandbox Code Playgroud)
网络回调实现:
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
logger.warn("NETWORK AVAILABLE: $network")
_connectivityState.update {
getConnectivityState()
}
}
override fun onCapabilitiesChanged(
network: Network,
networkCapabilities: NetworkCapabilities
) {
super.onCapabilitiesChanged(network, networkCapabilities)
logger.warn("NETWORK CAPABILITIES CHANGED: $network")
_connectivityState.update {
getConnectivityState()
}
}
override fun onLost(network: Network) {
super.onLost(network)
logger.warn("NETWORK LOST: $network")
_connectivityState.update {
getConnectivityState()
}
}
}
Run Code Online (Sandbox Code Playgroud)
getConnectivity 实现:
fun getConnectivityState(
network: Network? = connectivityManager.getActiveNetwork()
): ConnectivityState {
//these objects represent information about the currently active network
val capabilities = connectivityManager.getNetworkCapabilities(network)
val linkProperties = connectivityManager.getLinkProperties(network)
val connectivityState = ConnectivityState()
if(wifiManager.isWifiEnabled) {
//if wifi is enabled, it should be the current active network
val isWifi = capabilities?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
if(isWifi != null) {
if(isWifi) {
//the current active link is a WiFi connection
logger.info("Network is WiFi.")
connectivityState.source = ConnectivitySource.WIFI
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
logger.info("Version code: ${Build.VERSION.SDK_INT} >= ${Build.VERSION_CODES.S}, using capabilities.getTransportInfo()")
val transportInfo = capabilities.transportInfo
logger.info("Got TransportInfo")
if(transportInfo is WifiInfo) {
logger.info("TransportInfo 'is' WifiInfo")
connectivityState.ssid = transportInfo.ssid
logger.info("WifiInfo SSID" + connectivityState.ssid)
} else {
logger.info("TransportInfo 'is NOT' WifiInfo (" + transportInfo!!::class.qualifiedName + ")")
}
} else {
logger.info("Version code: ${Build.VERSION.SDK_INT} < ${Build.VERSION_CODES.S}, using wifiManager.connectionInfo")
//old method of obtaining WifiInfo through ConnectivityManager
val wifiInfo = wifiManager.connectionInfo
connectivityState.ssid = wifiInfo.ssid
logger.info("WifiInfo SSID" + connectivityState.ssid)
}
} else {
//the current link does not have the WiFi transport classification
logger.info("WiFi is enabled but network link is NOT WiFi!")
}
} else {
//can't get information about wifi?
logger.error("Unable to discover if network is WiFi! Transport == WiFi returned null.")
}
} else {
//wifi is disabled, but should probably be enabled for the app to connect
logger.warn("WiFi is disabled!")
}
val isCellular = capabilities?.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
if(isCellular != null) {
if(isCellular) {
logger.info("Network is cellular data.")
connectivityState.source = ConnectivitySource.CELLULAR
} else {
logger.info("Network is NOT cellular data.")
}
} else {
logger.error("Unable to discover if network is cellular! Transport == cellular returned null.")
}
return connectivityState
}
Run Code Online (Sandbox Code Playgroud)
相关日志行,为了便于阅读而进行了缩写:
NETWORK CAPABILITIES CHANGED: 272
Network is WiFi.
Version code: 34 >= 31, using capabilities.getTransportInfo()
Got TransportInfo
TransportInfo 'is NOT' WifiInfo (android.net.VpnTransportInfo)
Network is NOT cellular data.
Run Code Online (Sandbox Code Playgroud)
小智 0
android.net.VpnTransportInfo类没有记录在公共 SDK 中,它似乎是一个内部类或隐藏 API 的一部分。这可能就是您在 Android 官方文档中找不到有关它的信息的原因。
要在设备通过 VPN 连接时获取 SSID,您可以考虑使用替代方法。您可以使用 ConnectivityManager.getNetworkInfo (network)方法来获取有关网络的信息,然后将其转换为 WifiInfo 来获取 SSID,而不是依赖 Capability.transportInfo 属性。
我修改了您的代码,您可能想尝试一下:
override fun onCapabilitiesChanged(
network: Network,
networkCapabilities: NetworkCapabilities
) {
super.onCapabilitiesChanged(network, networkCapabilities)
logger.warn("NETWORK CAPABILITIES CHANGED: $network")
_connectivityState.update {
getConnectivityState(network)
}
}
// Modify getConnectivityState to take a network parameter
fun getConnectivityState(network: Network?): ConnectivityState {
val capabilities = connectivityManager.getNetworkCapabilities(network)
val linkProperties = connectivityManager.getLinkProperties(network)
val connectivityState = ConnectivityState()
if (wifiManager.isWifiEnabled) {
val isWifi = capabilities?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
if (isWifi != null && isWifi) {
val networkInfo = connectivityManager.getNetworkInfo(network)
if (networkInfo != null && networkInfo.type == ConnectivityManager.TYPE_WIFI) {
// Cast to WifiInfo and get the SSID
val wifiInfo = networkInfo.extraInfo as? WifiInfo
if (wifiInfo != null) {
connectivityState.ssid = wifiInfo.ssid
logger.info("WifiInfo SSID: ${connectivityState.ssid}")
} else {
logger.error("Failed to cast extraInfo to WifiInfo")
}
}
}
}
// ... (remaining code)
return connectivityState
}
In this modified code, getNetworkInfo(network) is used to obtain a NetworkInfo object, and extraInfo is then cast to WifiInfo to get the SSID. This approach should be more reliable and should work whether the device is connected through a VPN or not.
Run Code Online (Sandbox Code Playgroud)
请注意,此方法假设 Wi-Fi 网络的网络类型为 ConnectivityManager.TYPE_WIFI。
| 归档时间: |
|
| 查看次数: |
125 次 |
| 最近记录: |