在Android 6.0 Marshmallow上,应用(WiFi连接)不再起作用

4
我的应用程序在升级到Marshmallow后停止工作了,它原本应该能够更改WiFi连接,但现在根本没有任何反应。
我花了一些时间阅读Android 6.0的新权限模型。很棒,但旧应用程序应该继续工作...无论如何,我开始尝试实现授权,但意识到这是一个普通权限,如果在android清单中定义了它,则不需要进行权限请求:
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

权限一直在Android清单中,如果我理解正确,它应该可以工作,因为它是“普通权限”。那么为什么它不起作用,有没有人有解决方案?

以下是与我的情况相关的代码片段:

protected void connectWifi() {
    if ((!connectedToAccessPoint(settings.getMainConnectionName()))
            && (accessPointIsAvailable(settings.getMainConnectionName()))) {
        ConnectionUtils.connectToWifi(this,
                settings.getMainConnectionName(),
                settings.getMainConnectionPassword());
        Toast.makeText(this,
                "Connecting to " + settings.getMainConnectionName(),
                Toast.LENGTH_LONG).show();
        handler.postDelayed(sendUpdatesToUI,
                DelayConstants.BASIC_REQUEST_SENT);
        handler.postDelayed(sendUpdatesToUI,
                DelayConstants.CHANGE_CONNECTION);
    }
}

这里是与连接相关的技术部分:

public static void connectToWifi(Context context, String ssid, String password) {
     WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
     // setup a wifi configuration
      WifiConfiguration wc = new WifiConfiguration();
      wc.SSID = "\"" + ssid + "\"";
      wc.preSharedKey = "\""+ password + "\"";
      wc.status = WifiConfiguration.Status.ENABLED;
      wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
      wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
      wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
      wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
      wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
      wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
    // connect to and enable the connection
     int netId = wifiManager.addNetwork(wc);
     wifiManager.enableNetwork(netId, true);
     wifiManager.setWifiEnabled(true);
}

在之前提到的AndroidManifest中,有一个CHANGE_WIFI_STATE权限,这个权限在运行于没有Android 6.0的设备上时就已经存在了。

请提供一个 [mcve]。没有人能够帮助您看不到的代码。 - CommonsWare
@CommonsWare 抱歉,通常我会的,但这一次我不是很确定还需要发布什么?您需要什么代码?另外,您可以确认我正确理解概念-我不需要为此权限进行任何权限授予吗? - Arturas M
"我还需要在这里发布什么其他内容?"--你可以发布“应该能够更改WiFi连接”的代码,并确认“根本不做任何事情”的具体细节。“我不需要为此权限授予任何权限吗?”--这是Android 6.0中的普通权限,因此您不需要为此做任何特殊处理。但是,其他方面已经发生了变化(例如,WifiManager.getScanResults()需要位置权限,对WifiConfiguration的限制更改)。 - CommonsWare
如果这个后续变化与你的代码有关,这里是发布说明:http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-network - CommonsWare
@CommonsWare 我更新了我的问题,并附上了代码片段,您有什么想法可以解决这个问题吗?我认为这段代码是我一段时间前找到的适用于Android 5.0及以下版本的修改过的示例。 - Arturas M
显示剩余2条评论
2个回答

4

最终在网友的帮助下,我解决了这个问题。事实上,这是一个权限问题。

似乎在 Android 6.0 上使用 WifiManager 扫描连接时,需要访问您的位置信息,这可能是精确位置或大致位置,因此我将以下内容添加到清单文件中:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

我在我的代码中检查连接是否可用,然后再连接它,这就是为什么它从来没有工作过的原因,网络扫描总是返回0个结果,因为缺少权限。因此,在实现时需要以标准方式请求ACCESS_COARSE_LOCATION权限,否则除非你在Android中开启位置设置,否则它将不起作用。如果每次都需要开启位置设置,那么我的应用程序实际上就没什么用处了...
最后,我采取了一种绕路方法,没有检查接入点是否可用,而是使用try-catch语句尝试连接它。虽然这很丑陋,但这是新版Android中唯一的方法。
我确实喜欢新的权限模型,但显然Google在某些方面实施得非常糟糕。为什么现在需要开启位置才能获取WiFi扫描结果????在Android 6.0之前没有这样的要求。我理解关于位置权限的事情,但实际上必须开启位置才能扫描WiFi可用性就是完全错误的...

仅供参考,如果有人遇到这个答案,请注意添加位置服务以便首先扫描以定位要连接的网络。我认为Google认为扫描和扫描结果是一个隐私问题,并添加了位置服务要求,以便用户控制授权。 - Bruce

3
一个很好的教程建议:
Marshmallow上的应用程序需要ACCESS_COARSE_LOCATION或ACCESS_FINE_LOCATION权限,并且必须启用位置服务才能获得wifi扫描结果。您可以在以下链接中了解更多信息:http://www.intentfilter.com/2016/08/programatically-connecting-to-wifi.htmlMarshmallow开始,出现了一项限制,即应用程序只能修改它创建的那些WiFi网络。系统不允许修改其他应用程序或用户创建的网络。因此,如果该网络已经存在于列表中(系统可能会在检测到网络后自动连接到网络),则添加网络可能会失败。

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