当前位置: 首页 > 知识库问答 >
问题:

是否可以在Android Q上添加网络配置?

虞华彩
2023-03-14

我注意到在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帮助。

共有3个答案

洪胜涝
2023-03-14

看起来他们在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,我们有一些灰色区域,我还没有找到好的解决方案。如果有人有其他想法,请与我分享。;)

牧宁
2023-03-14

我希望我能回答你所有的问题,因为我目前正与类似的问题斗争。

数小时后,我终于能够使用以下方法连接到所需的网络:

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())
麹渊
2023-03-14

我也遇到了同样的问题,但不知何故,我达到了一个可复制的状态,可以连接到所需的网络,我想分享我的发现,这可能会有所帮助。

总结一下:你必须在应用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")
    }
}

以下是步骤:

  1. 安装新版本/或删除之前添加的所有建议

请注意以下事项:

  1. 如果您断开网络与Wifi设置的连接(即按下下图中的断开bin图标),即使您使用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 谢谢!!!