判断是否连接了wifi(坑、坑、坑)

在公司的一台Android球机设备上,制造商修改了系统,在连接wifi后,如果还插有sim卡,则网络是走sim卡的流量,不走wifi,所以此时我们ping wifi局域网的网关或局域网中别的ip是ping不通的,因为网络走的sim卡不走wifi。在这种情况下,一些判断wifi是否已连接的代码将失效(为什么此时我要判断wifi是否已连接?因为我要判断wifi是连接的话我就关闭sim卡数据流量,以让流量走wifi,如果wifi没连接我就开启sim卡数据流量,以让网络走sim卡。恶心的厂家乱改!)。

示例代码所需权限:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
fun isWifiConnected(): Boolean {
    val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val networkInfo = cm.activeNetworkInfo
    println("isConnected = ${networkInfo?.isConnected}")
    println("isMobile = ${networkInfo?.type == ConnectivityManager.TYPE_MOBILE}")
    return networkInfo != null && networkInfo.type == ConnectivityManager.TYPE_WIFI
}

用这个函数判断wifi是否连接是不准的,运行结果如下:

isConnected = true
isMobile = true

当前,设备是连接了wifi了的,但是由于系统被改为wifi和sim卡同时存在时走sim卡,所以这里获取的activeNetworkInfo是 sim卡的,并不是 wifi的。

同理,用下面的函数判断wifi是否已连接也是不准确的,如下:

private fun isWifiConnected(): Boolean {
    val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val activeNetwork = connectivityManager.activeNetwork
    val networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork)
    return networkCapabilities?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ?: false
}

下面的方式也不准:

fun isWifiConnected(): Boolean {
    val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val networkInfo = cm.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
    println("isConnected = ${networkInfo?.isConnected}")
    return networkInfo?.isConnected ?: false
}

运行结果如下:

isConnected = false

另一种方式来自ChatGPT:

fun isWifiConnected(): Boolean {
    val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
    println("networkId = ${wifiManager.connectionInfo.networkId}")
    return wifiManager.connectionInfo.networkId != -1
}

运行结果如下:

networkId = -1

明明连接了wifi了,但是它竟然返回-1,获取ssid也获取不到,后来查看connectionInfo的文档声明,发现它需要定位权限,于是把权限加上:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

加上权限再次运行就OK了,可以成功判断wifi是否连接。

另外我自己想了一个方式,因为wifi连接之后会分配到ip,所以我通过判断wifi网络接口是否有ip,有的话就是wifi已经连接上了,该方式需要网络权限,如下:

<uses-permission android:name="android.permission.INTERNET"/>
fun isWifiConnected(): Boolean {
    val networkInterface = NetworkInterface.getByName("wlan0")
    val inet4Address = networkInterface?.inetAddresses?.asSequence()?.find { it is Inet4Address }
    println("ip = ${inet4Address?.hostAddress}")
    return inet4Address != null
}

运行结果如下:

192.168.1.173

断开wifi连接再运行,结果如下:

ip = null

这里我们取了ipv4的ip地址,简单一点应该是只要有ip就行,不管你是ipv4还是ipv6,如下:

fun isWifiConnected(): Boolean {
    val networkInterface = NetworkInterface.getByName("wlan0")
    return networkInterface?.inetAddresses?.hasMoreElements() ?: false
}

这种方式虽然实现了我们需要的功能,但总感觉不是很正规的样子,Android官方有提供正规的方式,如 下:

fun isWifiConnected(): Boolean {
    val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val allNetworks = connectivityManager.allNetworks
    for (network in allNetworks) {
        val networkCapabilities = connectivityManager.getNetworkCapabilities(network)
        if (networkCapabilities != null && networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
            return true
        }
    }
    return false
}

在IDE中显示connectivityManager.allNetworks是过时的,然后推荐了另一种方式,如下:

fun isWifiConnected() {
    val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val request = NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .build()
    val networkCallback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: android.net.Network) {
            println("wifi已连接")
        }
        override fun onLost(network: android.net.Network) {
            println("wifi未连接")
        }
    }
    connectivityManager.registerNetworkCallback(request, networkCallback)
}

如上方法,当wifi是连接的情况下,它就像是个粘性广播,一调用register函数就会立马收到回调,但是如果wifi是未连接的情况下,调用register函数时不会收到回调,所以这点不是很好,感觉像是Android官方Bug,你推荐我们用这种方式,但是当wifi未连接时,调用register函数确实收不到回调通知。当我们已经调用注册了,此时才把wifi断开,这是可以收到回调的。所以,如果要监听wifi连接、断开的事件,可以使用这个注册回调的方式,如果要主动获取,则还是使用前一种方式,或者使用判断是否有ip的方式。

总结:可以准确获取wifi连接状态的方式有4种,如下:

fun isWifiConnected(): Boolean {
    val networkInterface = NetworkInterface.getByName("wlan0")
    return networkInterface?.inetAddresses?.hasMoreElements() ?: false
}
fun isWifiConnected(): Boolean {
    val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
    return wifiManager.connectionInfo.networkId != -1
}
fun isWifiConnected(): Boolean {
    val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val allNetworks = connectivityManager.allNetworks
    for (network in allNetworks) {
        val networkCapabilities = connectivityManager.getNetworkCapabilities(network)
        if (networkCapabilities != null && networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
            return true
        }
    }
    return false
}
fun isWifiConnected() {
    val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val request = NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .build()
    val networkCallback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: android.net.Network) {
            println("wifi已连接")
        }
        override fun onLost(network: android.net.Network) {
            println("wifi未连接")
        }
    }
    connectivityManager.registerNetworkCallback(request, networkCallback)
}

相关推荐

  1. 判断是否连接wifi

    2024-07-20 08:34:02       23 阅读
  2. springboot 连接hive的

    2024-07-20 08:34:02       30 阅读
  3. MyBatis中if判断(踩

    2024-07-20 08:34:02       24 阅读
  4. echart<span style='color:red;'>坑</span>

    echart

    2024-07-20 08:34:02      23 阅读
  5. Rocketmq的又来

    2024-07-20 08:34:02       17 阅读
  6. 【开发掉】go 中 interface 的 nil 判断

    2024-07-20 08:34:02       46 阅读
  7. Druid连接池工具公式化SQL附踩记录

    2024-07-20 08:34:02       54 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-20 08:34:02       52 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-20 08:34:02       54 阅读
  3. 在Django里面运行非项目文件

    2024-07-20 08:34:02       45 阅读
  4. Python语言-面向对象

    2024-07-20 08:34:02       55 阅读

热门阅读

  1. mybatis增删改查

    2024-07-20 08:34:02       9 阅读
  2. EXCEL的快捷方式

    2024-07-20 08:34:02       19 阅读
  3. open3d:ransac分割多个平面(源码)

    2024-07-20 08:34:02       16 阅读
  4. 第四节shell条件测试(3.2)(4)

    2024-07-20 08:34:02       18 阅读
  5. 鸿蒙仓颉语言【泛型generic】

    2024-07-20 08:34:02       15 阅读
  6. HTTP协议总结

    2024-07-20 08:34:02       17 阅读
  7. Spark SQL----DISTRIBUTE BY子句

    2024-07-20 08:34:02       19 阅读
  8. AI学习指南机器学习篇-t-SNE模型应用与Python实践

    2024-07-20 08:34:02       14 阅读
  9. 使用中转API进行大模型调用及PDF解析

    2024-07-20 08:34:02       20 阅读
  10. Apache Flink

    2024-07-20 08:34:02       16 阅读
  11. 在Linux(CentOS、Ubuntu等等)中安装Erlang和Elixir

    2024-07-20 08:34:02       18 阅读
  12. Ubuntu22.04版本的YOLOv8TensorRT模型部署

    2024-07-20 08:34:02       18 阅读
  13. MQTT 报文类型

    2024-07-20 08:34:02       15 阅读
  14. 探索WebKit的CSS列表与标记:美化列表的艺术

    2024-07-20 08:34:02       20 阅读