我注意到在WifiManager类中有一个名为addNetwork的函数,如果我想恢复或保存网络信息(网络名AKA SSID,以及密码和类型),它可能会很有用,这样我也可以连接到它。
我找不到多少关于如何做这样一件事的信息。我看过StackOverflow的各种例子,如果我针对Android API 28(或更低),我确实成功地让它添加了一个网络,甚至连接到它。
然而,当目标是Android29(AndroidQ)时,它无法添加网络。
由于我在Android Q beta 4上试用Pixel 2,我认为可能是因为addNetwork
不受欢迎,所以文档甚至这样说,如果我针对Android Q,它将不起作用,而且确实不起作用:
兼容性注意:对于以构建为目标的应用程序。VERSION_CODES。Q或更高,此API将始终返回-1。
在Android Q(不包括)之前,它的工作方式似乎是准备WifiConfiguration
并添加它。以后,如果我愿意,我也可以连接到它。在Android Q上,它似乎被WifineTworksSuggestion所取代,但它似乎根本不是关于添加一个网络:
网络建议对象用于在自动连接到网络时提供Wi-Fi网络以供考虑。应用程序无法直接创建此对象,它们必须使用WifineTworksSuggestion。生成器#build()获取此对象的实例。
应用程序可以使用WifiManager#addNetworkSuggestions(List)向平台提供此类网络的列表。
@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"/>
但在任何情况下,只要你不针对AndroidQ(API 29)及以上版本,这都是可行的。当你瞄准它时,我总是得到“-1”,这意味着它失败了。
我还在问题跟踪程序上发现了一个问题(在这里,我在这里写到了这个问题),它告诉我们有人需要回API,但我不确定这是关于添加网络的问题。
在查看WifiNetworkSugg的
时,我没有看到它有很多东西可以通过其生成器设置为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,认为我可能做得不正确,但它甚至没有显示通知。因为我认为这整个行为是一个bug,所以我在这里报告了它。
不仅如此,但我发现,如果它确实应该以这种或那种方式添加网络,它仍然有一些严重的限制,如最大添加网络(在这里)和卸载应用程序后被删除(在这里)
>
如果wifinetworkssuggestion
不是关于添加网络,那么它到底用于什么?
因为我对添加网络的花絮不够熟悉,所以我的代码对添加网络的所有可能方法都正确吗?我这么问是因为有人在这里写道,人们应该启用无线网络,并确保pingSupply icant返回true。是真的吗?或者仅仅调用addNetwork
就足够了吗?
如果现在无法使用普通API添加网络,是否有一种解决方案可以使用根设备替代?也许是亚洲开发银行的命令?
编辑:不知道如何正式实现,但使用adb,您可能可以在Android 11上添加Wifi网络。需要查看adb shell cmd wifi帮助。
看起来他们在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)
对话框看起来像这样:
然后我们只需要在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
}
}
}
但是当我在安装了旧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) }
看起来新方法不支持开箱即用。因此,对于API30,我们可以使用新的意图操作,对于API28及以下,我们仍然可以使用添加网络的旧方法,但是对于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())
我也遇到了同样的问题,但不知何故,我达到了一个可复制的状态,可以连接到所需的网络,我想分享我的发现,这可能会有所帮助。
总结一下:你必须在应用WifiNetworkSuggess
逻辑之前禁用所有自动连接
有关更多详细信息,请阅读以下内容:
我使用了以下代码(与您使用的代码类似):
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")
}
}
以下是步骤:
请注意以下事项:
wifiManager删除了建议的网络,您的网络也将被自动连接阻止24小时。移除网络建议(列表(it))
并再次添加。即使你卸载并再次安装你的应用程序不幸的是,这是Android系统增加的限制,如下所述:
如果用户在连接到某个网络时使用Wi-Fi选择器明确断开与该网络的连接,则该网络将被列入24小时黑名单。在黑名单期间,即使应用程序删除并重新添加与该网络对应的网络建议,该网络也不会被视为自动连接。
在同一应用提供的其他网络建议中指定此网络的优先级(优先级对不同应用的建议没有影响)。数字越高,优先级越高(即0=最低优先级的值)。
拒绝网络建议通知的用户将从应用程序中删除“更改WIFI”状态权限。用户可以稍后通过进入Wi-Fi控制菜单(设置)授予此批准
问题内容: 我使用VIRTUALENV与我的发展环境与利润,以及其他面向Web的包。 我将使用Qt开发一个简单的python客户端,以重复使用web.py开发的一些Api。 这里有人成功用Virtualenv安装了PyQt4吗? 可能吗? 我已经下载了所有二进制文件,并已全局安装在python2.6目录中。 如果我不使用该选项,Virtualenv会正确地包含在我的新沙箱中,但是显然会包含我不需要
我有一个ASP. net MVC 5项目,它在特定的API区域中包含一个WebAPI。我在我的web.config中启用了IIS7错误处理,如下所示: 当404/500等发生时,这将向MVC网站的用户显示友好的消息。当WebAPI返回特定的(合法的)状态代码时,我的问题就出现了(例如,当调用'/api/Token'时为400)。在这些情况下,响应的JSON内容被IIS拦截,我的友好消息超文本标记语
问题内容: 我想使用PdfPages将在脚本的不同部分创建的2个图形保存到PDF中,是否可以将它们附加到pdf? 例: 问题答案: 抱歉,这是一个la脚的问题。我们只是不应该使用该语句。
我正在尝试使用python wget下载URL,下载地址为:https://pypi.python.org/pypi/wget 这个包不支持超时选项,因此查询失败大约需要一些时间(大约10秒)。是否可以在try块中添加超时以减少函数的等待时间。 大概是这样的:
我需要添加一个单独的登录页面之前,招摇用户界面的身份验证从另一个服务器。从这个请求中,我将获得一个密钥,我必须将其添加到来自swagger UI的每个req的标头中。 我在swagger 2.0中使用节点服务器和swagger工具。
我对任何逻辑都是新手,我有一个问题我无法解决... 我把“布局类型”和“网络类型”设为“随机”,并勾选了“启动时申请”的复选框……一开始,我就有了一个不错的社交网络 然而代理的诞生和死亡...问题是,当我添加代理时,新创建的代理没有连接!所以我,当所有最初的特工都死了,我发现我自己有特工,但没有网络! 我该怎么办?添加新代理时,我希望它与其他代理连接:s 谢谢!!!