安卓WifiManager.addNetwork()返回-1

23

我正在编写一个Android应用程序,它将连接到特定的WPA接入点。连接成功后,它会发出一个HTTP调用。它不会保存网络配置。 我已经阅读了几乎所有有关连接WiFi网络的stackoverflow帖子,但找不到适合我的答案。这是我用来连接的代码。

    WifiConfiguration wc = new WifiConfiguration();
    wc.allowedAuthAlgorithms.clear();
    wc.allowedGroupCiphers.clear();
    wc.allowedPairwiseCiphers.clear();
    wc.allowedProtocols.clear();
    wc.allowedKeyManagement.clear();
    wc.SSID = "\"".concat("<ssid>").concat("\"");
    wc.preSharedKey = "\"".concat("<password>").concat("\"");
    wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
    wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
    wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
    wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
    wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
    wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
    wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
    wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN); // For WPA2
    wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA); // For WPA
    wc.priority = 0;
    //wc.hiddenSSID = true;
    wc.status = WifiConfiguration.Status.ENABLED;
    // connect to and enable the connection
    WifiManager wifiManager = (WifiManager) getSystemService(this.WIFI_SERVICE);
    int netId = wifiManager.addNetwork(wc);
    boolean wifiEnabled = wifiManager.enableNetwork(netId, true);
    wifiManager.setWifiEnabled(true);
    Log.d("opener", "addNetwork returned " + netId);
    if (netId > 0) {
        wifiId = netId;
    }

然而,netId总是-1。我在两部不同的手机上尝试了这个代码(ICS:HTC Rezound和GingerBread:Motorola DroidX)。它们都显示完全相同的结果。 我做错了什么?

编辑:我尝试使用WPA2接入点运行相同的代码,并得到非常奇怪的结果。当运行此代码时,第一次会返回-1,但如果我延迟1秒后再次调用相同的方法,则会返回有效的netId。所以问题是:

  1. 为什么上面的代码不能连接到WPA?
  2. 在WPA2中,为什么我需要调用上述方法两次才能连接?编辑:我观察到我必须多次连接才能连接。有时要连接3-4次才能连接。因此,现在我正在循环执行,直到添加配置返回> 0的ID。

4
你解决了吗?我正在遇到完全相同的问题... - Sebastian Breit
我遇到了类似的问题。我的addNetwork调用失败并返回-1。有人解决了这个问题吗? - Aaron
5个回答

16

或许有点晚了,但尝试一下这种方法来连接Open/WPA/WPA2/WEP加密的网络。

    WifiConfiguration wifiConfig = new WifiConfiguration();
    wifiConfig.SSID = selectedNetwork.SSID();
    wifiConfig.status = WifiConfiguration.Status.DISABLED;
    wifiConfig.priority = 40;

    // Dependent on the security type of the selected network
    // we set the security settings for the configuration
    if (/*Open network*/) {
        // No security
        wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        wifiConfig.allowedAuthAlgorithms.clear();
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
    } else if (/*WPA*/ || /*WPA2*/) {
        //WPA/WPA2 Security
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        wifiConfig.preSharedKey = "\"".concat(password).concat("\"");
    } else if (/*WEP*/) {
        // WEP Security
        wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        wifiConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
        wifiConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        wifiConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        wifiConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);

        if (getHexKey(password)) wifiConfig.wepKeys[0] = password;
        else wifiConfig.wepKeys[0] = "\"".concat(password).concat("\"");
        wifiConfig.wepTxKeyIndex = 0;
    }

    // Finally we add the new configuration to the managed list of networks
    int networkID = wifiMan.addNetwork(wifiConfig);

显然,根据适用情况设置不同安全类型的自变量。连接到一个WEP安全网络的关键(请原谅双关语)是以下的getHexKey方法。

/**
 * WEP has two kinds of password, a hex value that specifies the key or
 * a character string used to generate the real hex. This checks what kind of
 * password has been supplied. The checks correspond to WEP40, WEP104 & WEP232
 * @param s
 * @return
 */
private static boolean getHexKey(String s) {
    if (s == null) {
        return false;
    }

    int len = s.length();
    if (len != 10 && len != 26 && len != 58) {
        return false;
    }

    for (int i = 0; i < len; ++i) {
        char c = s.charAt(i);
        if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
            continue;
        }
        return false;
    }
    return true;
}

1
在我的测试中,仅需要调用wifiConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);部分来处理开放网络。 - ThomasW

10
我发现如果共享密钥少于8个字符,它将返回-1。

你说得对,我也发现这取决于长度,那么你知道解决方案吗? - Ashish Jain

8
问题在于您正在尝试添加已经存在的网络配置。当您调用以下命令时:
int netId = wifiManager.addNetwork(wc);

如果具有相同SSID的网络配置已经存在,它将失败(返回-1)。因此,您需要检查netId是否为-1,如果是,则遍历配置的网络搜索具有相同SSID的网络,一旦找到,返回networkId。

Kotlin:

var netId = wifiManager.addNetwork(conf)
if (netId == -1) netId = wifiManager.configuredNetworks?.let {
    it.firstOrNull { it.SSID.trim('"') == ssid.trim('"') }?.networkId ?: -1
}
wifiManager.enableNetwork(netId, true)

5

我遇到过同样的问题。我发现在调用addNetwork时,你的wifi必须处于开启状态。


3
你可以在评论中使用这个。 - tod

5

我刚刚遇到了同样的问题。一开始似乎一切正常,但后来就不行了。

我找到了以下内容:

  • Android WifiStateMachine将不允许您在supplicant未运行且未连接时添加或修改网络。这会影响在启动时运行的服务和即使WIFI关闭也会运行的服务。

  • Android WifiConfigStore通过UID跟踪wifi网络的所有者。这意味着您可能无法修改由另一个进程创建的网络。

正确的方法来添加网络是:

  1. 检查WIFI网络是否已启用。如果没有,请调用WifiManager.setWifiEnabled(true)
  2. 等待WifiManager.pingSupplicant()返回true。
  3. 创建并填充新的WifiConfiguration,然后将其传递给WifiManager.addNetwork()。确保返回值不为(-1)。
  4. (可选)使用addNetwork()返回的值作为WifiConfiguration.enableNetwork()调用的参数(除非它为-1)。请注意,布尔参数表示disableOthers,应该是false,除非您有权修改所有其他网络:如果将其设置为true,则可能会在内部失败。

这应该允许您以编程方式添加(和连接)到新的Wifi网络。


2
我在文档和整个互联网上都找不到任何关于android.permissions.OVERRIDE_WIFI_CONFIG权限的提及。你能详细说明一下你从哪里得到的吗? - Lukas Knuth
没有 android.permission.OVERRIDE_WIFI_CONFIG 这样的东西。 - ChumiestBucket
我更新了答案,删除了关于权限的明显错误行。 - tir38
你知道如何在针对Android Q时添加网络吗?似乎整个API都无法工作,我想知道现在是否可能。请参见:https://dev59.com/dek5XIcBkEYKwwoY49sn - android developer
这个解决方案添加了网络,但在我的情况下,它没有将我的设备连接到自定义网络。你知道问题可能出在哪里吗? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接