背景
我注意到在WifiManager类中有一个名为addNetwork的函数,如果想要恢复或保存网络信息(网络名称即SSID,包括密码和类型),则该函数可能非常有用,以便后续可以连接到网络。
问题
我找不到如何实现这样的功能的详细信息。我在StackOverflow上看到了各种示例,如果我针对Android API 28(或更低版本)进行操作,则确实可以添加一个网络并连接到它。
然而,当针对Android 29(Android Q)时,它无法添加网络。
我所发现的
由于我正在尝试使用安装有Android Q beta 4的Pixel 2,因此我认为可能是因为addNetwork
被弃用了,因此文档甚至这样说,并且如果我针对Android Q进行操作,则它将无法正常工作,实际上它确实无法正常工作:
兼容性说明:针对Build.VERSION_CODES.Q或更高版本的应用程序,此API将始终返回-1。
在Android Q之前,它似乎应该按照以下方式工作:准备WifiConfiguration
并添加它。以后,如果需要,可以连接到它。在Android Q上,它似乎被WifiNetworkSuggestion取代,但似乎与添加网络无关:
网络建议对象用于提供考虑自动连接到网络时的Wi-Fi网络。应用程序不能直接创建此对象,必须使用WifiNetworkSuggestion.Builder#build()来获取此对象的实例。
应用程序可以使用WifiManager#addNetworkSuggestions(List)向平台提供这些网络的列表。
这是我的当前代码,用于Android Q之前。
@WorkerThread
fun addNetwork(context: Context, networkName: String, networkPassword: String? = null, keyMgmt: Int = WifiConfiguration.KeyMgmt.NONE) {
val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
val conf = WifiConfiguration()
conf.SSID = "\"$networkName\""
conf.preSharedKey = if (networkPassword.isNullOrEmpty()) "" else "\"$networkPassword\""
conf.allowedKeyManagement.set(keyMgmt)
when (keyMgmt) {
WifiConfiguration.KeyMgmt.WPA_PSK -> {
//WPA/WPA2
}
WifiConfiguration.KeyMgmt.IEEE8021X -> {
}
WifiConfiguration.KeyMgmt.WPA_EAP -> {
}
WifiConfiguration.KeyMgmt.NONE -> {
if (networkPassword.isNullOrEmpty()) {
//open network
conf.wepKeys[0] = "\"\""
} else {
//wep
conf.wepKeys[0] = "\"" + networkPassword + "\""
conf.wepTxKeyIndex = 0
conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40)
}
}
}
if (networkPassword.isNullOrEmpty()) {
//open network
conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
} else {
}
wifiManager.isWifiEnabled = true
while (!wifiManager.pingSupplicant()) {
Log.d("AppLog", "waiting to be able to add network")
}
val networkId = wifiManager.addNetwork(conf)
if (networkId == -1)
Log.d("AppLog", "failed to add network")
else {
wifiManager.enableNetwork(networkId, false)
Log.d("AppLog", "success to add network")
}
}
看起来只需要这些权限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
但无论如何,只要不针对Android Q(API 29)及以上版本,这都可以正常工作。当你针对它时,我确实总是得到"-1"的结果,意味着失败。
我还在问题跟踪器上找到了一个问题(这里), 我也写了相关内容 这里), 描述了有人需要该API版本,但我不确定是否涉及添加网络。
查看WifiNetworkSuggestion
,我没有像通过构建器设置WifiConfiguration
那么多的东西,所以这是我怀疑它不是关于添加网络的另一个原因。
但我还是尝试了。下面是我尝试的代码,例如添加一个普通的WPA网络:
@WorkerThread
fun addNetworkAndroidQ(context: Context, networkName: String, networkPassword: String? = null) {
val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
val list = ArrayList<WifiNetworkSuggestion>()
val builder = WifiNetworkSuggestion.Builder().setSsid(networkName)
if (!networkPassword.isNullOrEmpty())
builder.setWpa2Passphrase(networkPassword)
list.add(builder.build())
val result = wifiManager.addNetworkSuggestions(list)
if (result == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS)
Log.d("AppLog", "success")
else Log.d("AppLog", "failed")
}
在运行时(我提供了我的WiFi网络详细信息,并使操作系统忘记它后),它说它成功了,但是操作系统的WiFi设置中没有出现任何东西。该网络不存在,密码也没有被添加。所以我真的不知道它做了什么......
几秒钟后,我注意到了一个通知,询问我是否可以连接应用程序建议的网络:
但是当我选择接受时,它仍然没有做任何事情,就像之前一样。
我尝试制作另一个POC,以为可能做错了,但是那时它甚至没有显示通知。由于我认为整个行为都是错误,我已经在这里报告了这个问题。
不仅如此,我还发现如果确实有一种方法可以添加网络,它仍然有一些严重的限制,例如最大添加网络数(这里)和在卸载应用程序时被删除(这里)。
问题
应该如何精确处理Android Q?确实不再有API可以添加网络了吗?
如果WifiNetworkSuggestion不是用于添加网络,那么它究竟被用于什么?
由于我对添加网络的细节不太熟悉,我的代码是否正确涵盖了所有可能的添加网络方式?我之所以问这个问题,是因为有人在这里写道,人们应该启用Wifi并确保pingSupplicant返回true。这是真的吗?还是只调用addNetwork就足够了?
如果现在使用常规API无法添加网络,那么也许使用rooted设备会有解决方案吗?也许有一些adb命令?
编辑:不确定如何正式做,但使用adb,您可能能够在Android 11上添加WiFi网络。需要检查adb shell cmd wifi help
。