我正在开发一个Wifi自动连接功能,我很震惊这个API是多么糟糕.

我现在使用了5种不同的API,但我仍然无法以用户预期的方式获得它.

我有一个在Android 10+上启用wifi自动连接的设置,我将try 以下方法:

  1. 判断我是否持有ACCESS_WIFI_STATE权限:
  2. 当我获得许可后,我会在Android 11+上判断我之前的wifi建议是否保存了wifiManager.networkSuggestions.isNotEmpty()如果是真的,我会判断我当前连接的wifi,请参阅步骤x.在较低级别上,我会跳过此步骤并转至步骤3
  3. 我使用wifi建议API和WifiNetworkSuggestion.Builder(),并建议用户使用我的wifi
  4. 当用户接受我的建议时,到目前为止我很好.我无法在Android 10上验证我的建议是否被接受.在Android 11上,这是可能的(参见步骤2).然而,我仍然不知道设备是否真的连接了wifi.所以我进入第7步
  5. 当用户拒绝我的建议时,我几乎退出了游戏,我再也不能问用户了(从技术上讲,有一个隐藏良好的功能,你可以切换权限,但没有用户会找到它).在安卓10上,我只需判断我是否连接了正确的wifi,至少理论上是这样(见第7步).
  6. 在安卓11+上,我可以退回到Settings.ACTION_WIFI_ADD_NETWORKS意图,它总是可以添加wifi(缺点是用户可以共享wifi密码)
  7. 我需要验证之前的步骤是否有效,用户是否实际连接到所需的wifi.为此,我已经拥有权限ACCESS_WIFI_STATEACCESS_NETWORK_STATEACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION.然而,ConnectivityManager API并没有返回实际的SSID,这让我抓狂.
  8. 如果用户没有连接到正确的wifi,我会try 使用Settings.Panel.ACTION_WIFI操作让用户连接到正确的wifi

总结一下:

  • 我使用WifiNetworkSuggestion API
  • 如果可能的话,我会退到Settings.ACTION_WIFI_ADD_NETWORKS
  • 我try 验证用户当前是否连接到了正确的wifi
  • 我try 通过Settings.Panel.ACTION_WIFI操作帮助用户连接到正确的wifi(甚至打开wifi)

这真的是一团糟还是有更简单的方法?


我目前正在访问SSID,如下所示:

private val currentSsid: String?
    get() =
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            val wifiInfo = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)?.transportInfo as? WifiInfo
            wifiInfo?.ssid
        } else {
            wifiManager.connectionInfo?.ssid
        }

基于Unable to get WIFI SSID using onCapabilitiesChanged in Android 12,我认为我访问值的方式不受支持.我现在得到的值是"<unknown ssid>".

推荐答案

答案只有一半,但可能会有帮助.以下是我获取用户当前SSID的方式(您需要持有位置权限):

fun updateSsid(networkCapabilities: NetworkCapabilities) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        currentSsid = (networkCapabilities.transportInfo as? WifiInfo)?.ssid?.trim('"')
    }
}

wifiCallback = when {
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
        object: ConnectivityManager.NetworkCallback(FLAG_INCLUDE_LOCATION_INFO) {
            override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
                updateSsid(networkCapabilities)
            }
        }
    }
    Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> {
        object: ConnectivityManager.NetworkCallback() {
            override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
                updateSsid(networkCapabilities)
            }
        }
    }
    else -> null
}

wifiCallback?.let {
    fragment.lifecycle.addObserver(object: DefaultLifecycleObserver {
        override fun onResume(owner: LifecycleOwner) {
            connectivityManager.registerNetworkCallback(request, it)
        }

        override fun onPause(owner: LifecycleOwner) {
            connectivityManager.unregisterNetworkCallback(it)
        }
    })
}

因此,基本上代码的各个方面都需要判断API的级别<;10、10、11和12.真是一团糟.

如果您想让用户 Select 配置的wifi,这可能非常方便:

fun showWifiDialog() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        try {
            fragment.startActivity(Intent(android.provider.Settings.Panel.ACTION_WIFI))
        } catch (e: Exception) {
            // ignored
        }
    }
}

Android相关问答推荐

当我的Log.i()不在主线程中时,如何在我的logcat中显示它?

以正确的方式从房间收集流量

滑动以更改合成中的活动

当X为lambda函数时,如何避免Android Studio错误检测参数X未使用?

推断的类型是片段,但应为上下文

如何消除脚手架和顶杆(material 3)更改 colored颜色 时的延迟?

如何在使用带有底部导航组件的片段管理器时更改片段工具栏的标签

Dispatchers中的Kotlin协同程序.Main没有';t块主螺纹

React-Native Manifest 合并失败并出现多个错误

如何在 compose android中将图像覆盖在另一个图像上

面向Jetpack Compose的可组合放置问题

是什么导致调用 Firebase 服务器?

如何在Android中使用嵌套的Recyclerview

在 MVVM Jetpack Compose 上添加依赖项时出现重复类错误

Android Studio 复制类 kotlin

Android collectAsStateWithLifecycle() 不在可组合内部收集

Android Studio Emulator Internet 连接问题仅是第一次

如何使用 Glide 将图像下载到设备内部存储

如果我在网络请求中指定它们是否与判断网络功能相关

如何使在库范围之外无法访问的接口的具体实现.?