16

我正在开发一个用户必须遵循以下步骤的应用程序:

  1. 将手机连接到wifi;
  2. 将手机从连接对象连接到专用热点。

当用户连接到连接对象的专用热点时,应用程序会执行一些 HTTP 请求以对其进行配置。然后,我想将应用程序自动重新连接到步骤 1 的全局 wifi。

从 API 21 到 API 28,这个功能很容易实现,因为我知道我也想重新连接手机的 SSID。只需几行代码即可完成:

private fun changeCurrentWifiNetworkLegacy(ssidToConnect: String) {
    val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager

    var ssidIdentifier: Int? = null

    wifiManager.configuredNetworks?.forEach { config ->
        Log.d("SSID", config.SSID)

        if (config.SSID == "\"${ssidToConnect}\"") {
            ssidIdentifier = config.networkId
        }
    }

    ssidIdentifier?.let { id ->
        wifiManager.enableNetwork(id, true)
    }
}

根据这篇文章,在 API 29 上这个简单的代码不再起作用:https ://developer.android.com/about/versions/10/privacy/changes#configure-wifi

根据文章,现在,我应该使用 2 个类:WifiNetworkSpecifier和/或WifiNetworkSuggestion.

不幸的是,我找不到使用这些类来将用户连接到以前配置的 SSID 的工作示例。

有人已经做到了吗?

预先感谢您的帮助。

4

3 回答 3

8

以防万一任何可怜的灵魂遇到这种情况,完全有可能您的设备上的 API 被破坏了。在我的 OnePlus 5、Android 10、Build 200513 上,会发生这种情况:

  1. 调用请求网络。不管我是使用 Listener 还是 PendingIntent 版本
  2. 操作系统找到网络,连接,onAvailable 和朋友被调用
  3. 操作系统立即断开连接。我可以在 logcat 中看到“应用程序发布请求,取消 NetworkRequest”
  4. 然而,这不是真的 - 请求没有被取消,Android 依赖它,并再次开始连接到网络的过程。转到 2. 并永远重复。

为此创建了一个 Android 错误:https ://issuetracker.google.com/issues/158344328

此外,如果您不以正确的顺序终止您的应用程序和对话框,并且只有重新启动有帮助,您可以让操作系统进入状态,当它不再显示“与设备一起使用”对话框时。

只需省去麻烦,以 Android 9 为目标并使用 WifiManager API(如果您以 10 为目标,这些 API 会很有帮助)。它甚至比新的 requestNetwork API 具有更好的用户体验。

于 2020-06-06T15:33:07.373 回答
3

您可以使用以下代码设置要连接的网络:

if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
    val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    val networkRequest = NetworkRequest.Builder()
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .setNetworkSpecifier(
            WifiNetworkSpecifier.Builder()
                .setSsid("My ssid")
                .build()
        )
        .build()
    cm.requestNetwork(networkRequest, object: ConnectivityManager.NetworkCallback() {
        override fun onUnavailable() {
            Log.d("TEST", "Network unavailable")
        }

        override fun onAvailable(network: Network) {
            Log.d("TEST", "Network available")
        }
    })
}

这使用 ConnectivityManager 的networkRequest方法来请求具有特定 SSID 的网络。

此方法要求调用者持有Manifest.permission.CHANGE_NETWORK_STATE由 确定的修改系统设置的权限或能力Settings.System.canWrite(Context)

有关您可以获得哪些信息的更多文档,请参阅NetworkCallback类。

(编辑:错过添加运输类型。)

进一步编辑:我需要使用.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)它才能正常工作。因为在 WifiNetworkSpecifier

只能用于请求本地 wifi 网络(即没有互联网功能)

根据文档

这给了我一个设备弹出请求,但最终向我显示了我要求的 Wifi 网络。

于 2019-11-08T16:23:19.847 回答
0

我尝试了很多代码,包括WifiManager.addNetworkSuggestionsand ConnectivityManager.requestNetwork。最后我发现,只需调用ConnectivityManager.unregisterNetworkCallback恢复用户wifi连接。这段代码唯一让我不满意的地方,如果用户保存了WiFi A和WiFi B,那么系统会自动选择一个连接,而不是我指定的那个。

于 2021-06-30T08:23:47.267 回答