and*_*per 6 android wifimanager android-wifi android-10.0
我注意到,在WifiManager类中有一个名为addNetwork的函数,如果我想恢复或保存网络信息(网络名称AKA SSID以及密码和类型),该功能可能很有用,以便我也可以连接到它。
我找不到有关如何执行此操作的太多信息。我在StackOverflow上看到了各种示例,并且如果我以Android API 28(或更低版本)为目标,那么我确实成功地使它添加了网络,甚至连接到它。
但是,以Android 29(Android Q)为目标时,它无法添加网络。
由于我正在尝试使用Android Q beta 4的Pixel 2,我认为可能是因为addNetwork已弃用,所以文档甚至说了这一点,并且如果我定位到Android Q,它将无法正常工作,并且确实无法使用工作:
兼容性说明:对于面向Build.VERSION_CODES.Q或更高版本的应用程序,此API始终返回-1。
通过准备WifiConfiguration和添加,看来它应该可以运行到Android Q(不包括)的方式。以后,我也可以根据需要连接到它。在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")
}
}
Run Code Online (Sandbox Code Playgroud)
似乎只需要这些权限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
Run Code Online (Sandbox Code Playgroud)
但无论如何,只要您不针对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")
}
Run Code Online (Sandbox Code Playgroud)
运行时(我让它忘记了操作系统,我给了它Wifi网络详细信息),它说成功了,但是OS的Wifi设置上什么也没有发生。使用我添加的密码,该网络不存在。所以我真的不知道它做了什么...
几秒钟后,我注意到一条通知,询问我是否可以连接到该应用程序建议的网络:
但是当我选择接受时,它还是没有做任何事情。
我试图制作另一个POC,以为我可能做错了,但后来它甚至没有显示通知。由于我认为整个行为都是错误,因此我在这里进行了报道。
不仅如此,而且我发现,如果确实应该以一种或另一种方式添加网络,它仍然有一些严重的限制,例如最大添加的网络(在此处)以及在卸载应用程序时被删除(在此处))
如何正确处理Android Q?真的没有API可以添加网络了吗?
如果WifiNetworkSuggestion不是要添加网络,那么它到底是用来做什么的?
由于我对添加网络的窍门还不熟悉,因此我的代码关于添加网络的所有可能方式是否正确?我之所以这样问,是因为有人在这里写道,人们应该启用Wifi并确保pingSupplicant返回的值是true。是真的吗 还是打电话就足够了addNetwork?
如果现在无法使用常规API添加网络,那么是否可以通过使用有根设备代替解决方案?也许一些adb命令?
我遇到了同样的问题,但不知何故,我达到了连接所需网络的可重现状态,我想分享我的发现,这可能会有所帮助。
总结:
在应用WifiNetworkSuggestion逻辑之前,您必须禁用所有自动连接
欲知更多详情,请阅读以下内容:
我使用了以下代码(类似于您使用的代码):
private fun connectUsingNetworkSuggestion(ssid: String, password: String) {
val wifiNetworkSuggestion = WifiNetworkSuggestion.Builder()
.setSsid(ssid)
.setWpa2Passphrase(password)
.build()
// Optional (Wait for post connection broadcast to one of your suggestions)
val intentFilter =
IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);
val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (!intent.action.equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
return
}
showToast("Connection Suggestion Succeeded")
// do post connect processing here
}
}
registerReceiver(broadcastReceiver, intentFilter)
lastSuggestedNetwork?.let {
val status = wifiManager.removeNetworkSuggestions(listOf(it))
Log.i("WifiNetworkSuggestion", "Removing Network suggestions status is $status")
}
val suggestionsList = listOf(wifiNetworkSuggestion)
var status = wifiManager.addNetworkSuggestions(suggestionsList)
Log.i("WifiNetworkSuggestion", "Adding Network suggestions status is $status")
if (status == WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE) {
showToast("Suggestion Update Needed")
status = wifiManager.removeNetworkSuggestions(suggestionsList)
Log.i("WifiNetworkSuggestion", "Removing Network suggestions status is $status")
status = wifiManager.addNetworkSuggestions(suggestionsList)
}
if (status == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
lastSuggestedNetwork = wifiNetworkSuggestion
lastSuggestedNetworkSSID = ssid
showToast("Suggestion Added")
}
}
Run Code Online (Sandbox Code Playgroud)
所以这里是步骤:
6.当您按“是”时,系统将通过您的应用程序自动连接它,互联网将正常工作。请参阅以下内容:
请注意以下事项:
wifiManager.removeNetworkSuggestions(listOf(it))并重新添加,您的网络也会被阻止 24 小时自动连接。即使您再次卸载并安装您的应用程序不幸的是,这是Android系统的加入限制描述在这里:
如果用户在连接到某个网络建议时使用 Wi-Fi 选择器明确断开与该网络建议的连接,则该网络将被列入黑名单 24 小时。在黑名单期间,该网络不会被考虑自动连接,即使应用程序删除并重新添加与该网络对应的网络建议。
WifiNetworkSuggestion.Builder().setPriority(<Priority Integer>)提到的方法优先考虑它们:指定该网络在同一应用提供的其他网络建议中的优先级(优先级对不同应用的建议没有影响)。数字越大,优先级越高(即值 0 = 最低优先级)。
(Settings > Apps & notifications > Special App access > Wi-Fi Control > App name)按照此处所述进行更改:拒绝网络建议通知的用户会从应用程序中删除 CHANGE_WIFI_STATE 权限。用户可以稍后通过进入 Wi-Fi 控制菜单(设置 > 应用程序和通知 > 特殊应用程序访问 > Wi-Fi 控制 > 应用程序名称)来授予此批准。
看起来他们在 Android 11(API 30)中添加了支持,用于添加在应用程序范围之外持续存在的网络配置,并保存为系统网络配置,就像使用已弃用的 WiFiManager 方法addNetwork所做的那样。您需要做的就是使用ACTION_WIFI_ADD_NETWORKS显示一个系统对话框,询问用户是否要继续向系统添加新的 Wifi 建议。这就是我们启动该对话框的方式:
// used imports
import android.provider.Settings.ACTION_WIFI_ADD_NETWORKS
import android.provider.Settings.EXTRA_WIFI_NETWORK_LIST
import android.app.Activity
import android.content.Intent
import android.net.wifi.WifiNetworkSuggestion
// show system dialog for adding new network configuration
val wifiSuggestionBuilder = WifiNetworkSuggestion.Builder()
.setSsid("network SSID")
.build()
val suggestionsList = arraylistOf(wifiSuggestionBuilder)
val intent = new Intent(ACTION_WIFI_ADD_NETWORKS)
intent.putParcelableArrayListExtra(EXTRA_WIFI_NETWORK_LIST, suggestionsList);
activity.startActivityForResult(intent, 1000)
Run Code Online (Sandbox Code Playgroud)
该对话框如下所示:
然后我们只需要在onActivityResult这样的方法中处理结果:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == 1000) {
if (resultCode == Activity.RESULT_OK) {
// network succesfully added - User pressed Save
} else if (resultCode == Activity.RESULT_CANCELED) {
// failed attempt of adding network to system - User pressed Cancel
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,当我在安装了较旧 Android 版本(低于 API30)的 Android 设备上测试此代码时,每次我希望它显示用于添加新网络配置的对话框时,我都会崩溃。这是崩溃的情况:
java.lang.RuntimeException: Unable to start activity: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.settings.WIFI_ADD_NETWORKS (has extras) }
Run Code Online (Sandbox Code Playgroud)
看起来新方法并不是开箱即用的。因此,对于 API30,我们可以使用新的 Intent 操作,对于 API 28 及以下版本,我们仍然可以使用添加网络的旧方法,但对于 API29,我们有某种灰色区域,我还无法找到好的解决方案。如果有人知道还能做什么,请与我分享。;)
我希望我能回答您所有的问题,因为我目前正在努力解决类似的问题。
经过几个小时后,我终于能够使用以下方法连接到所需的网络:
val wifiNetworkSpecifier = WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.setWpa2Passphrase(passphrase)
.setBssid(mac)
.build()
val networkRequest = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(wifiNetworkSpecifier)
.build()
val connectivityManager = applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
connectivityManager?.requestNetwork(networkRequest, ConnectivityManager.NetworkCallback())
Run Code Online (Sandbox Code Playgroud)
您可以通过 接收大量事件ConnectivityManager.NetworkCallback()。
| 归档时间: |
|
| 查看次数: |
822 次 |
| 最近记录: |