通过程序连接WiFi后,几秒钟后自动断开连接。

6
我遇到了一个问题,需要代表用户切换wifi网络。我们有一个物联网设备需要连接才能进行设置。使用WifiManagerConnectivityManager,我可以建立连接并进行REST调用,但是大约10秒后它就会切换回去。我不明白为什么会这样。有几行来自设备的奇怪日志,我确定它们是相关的,但我不知道如何修复,主要包括:
02-12 15:36:13.441 E/WifiConfigManager: UID 10356 does not have permission to update configuration "REDACTED"NONE
02-12 15:36:13.442 I/WifiStateMachine: connectToUserSelectNetwork Allowing uid 10356 with insufficient permissions to connect=90
...
02-12 15:36:13.470 E/WifiVendorHal: stopRssiMonitoring(l.2156) failed {.code = ERROR_NOT_AVAILABLE, .description = }
02-12 15:36:13.470 W/WifiConfigManager: Looking up network with invalid networkId -1
...
02-12 15:36:16.882 D/WifiStateMachine: NETWORK_STATUS_UNWANTED_VALIDATION_FAILED
...
02-12 15:36:17.041 D/WifiPermissionsUtil: Denied: no location permission

这里涉及到很多关于权限的内容,但我认为我需要请求所有权限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

我请求获取位置的RuntimePermission,因为我正在使用SDK 27的设备进行测试。更重要的是,它确实让我连接,但几秒钟后就改变了想法。


1
是的,我也遇到了同样的问题,但是我还是无法解决它...非常烦人,我甚至尝试使用bindProcessToNetwork,但仍然存在这些问题:( - sMyles
1
你找到解决方案了吗? - Keselme
2个回答

6
当尝试使用WifiManager.startScan()扫描网络时,会出现问题,因为Android已更改其权限模型。您需要检查运行时权限以访问粗略/精细位置,并且还必须检查位置提供程序(GPS)是否打开。否则,您将无法获取任何位置更新。在您的情况下,位置更新还包括您已扫描的wifi SSID。
此外,请注意,必须检查用户以前是否未通过系统设置连接到该设备,因为应用程序不允许从应用程序内部连接到用户定义的访问点。为了允许应用程序代表用户再次连接,用户必须在系统设置中删除/忘记该网络。如果不检查,子系统将返回supplicant身份验证错误。
对于物联网Wifi设备的其他注意事项:它们大多是“无头”访问点,即没有互联网。许多Android设备存在问题,需要一个有效的强制性门户网站。请参见此问题:https://android.stackexchange.com/questions/130265/stay-connected-to-specific-wifi-which-has-no-internet 要解决此问题,您必须使用静态IP地址进行连接。然而,Android不提供API以编程方式设置此内容。因此,您必须使用反射,如在此处所述:Set static IP and gateway programmatically in Android 6.x (Marshmallow)

5

在尝试连接现有WiFi配置时,我有一个类似的经历,我发现Denis的回答非常有帮助。以下是我在运行Android 8.1.0的Nexus 5x上发现的结果:

当一切正常时:

为了保持与没有互联网访问权限的WiFi网络的持久连接,你需要执行以下操作之一:

  • (a) 在该网络上调用bindToProcess(),告诉你的应用程序将其所有流量路由到该网络,尽管缺乏Internet连接

  • (b) 或者您可以配置HTTP客户端以使用所需网络的套接字工厂。

如果你使用你的应用程序创建的WiFi配置之一执行任何一项操作,系统不会因缺乏Internet访问权限而从网络中断开你。

当它们不起作用时:

如果你尝试连接的WiFi配置不是由你的应用程序(基于应用程序的UID)创建的,则仍然可以连接,并且可以执行 (a) (b),但系统将在短时间内断开你与该网络的连接。这对我来说似乎是Android的一个错误。系统允许你连接到你没有创建的配置,但会报告以下内容:

UID xxxxx does not have permission to update configuration

connectToUserSelectNetwork Allowing uid xxxxx with insufficient permissions to connect=16

不久之后,它会像你没有执行(a)(b)一样断开与配置的网络的连接。这似乎是 Android 系统中某个部分实现的 bug,因为如果不能访问互联网,你就不应该能够首先连接到该网络,或者应该允许使用(a)(b)维持连接。

当用户通过系统 WiFi 设置手动配置该网络时,或在 Android Studio 中重新运行应用程序时,WiFi 配置不被认为是由您的应用创建的两种情况。所以,如果您正在调试并配置网络,然后重新运行应用程序,则无法保持与先前配置的网络的持久连接,因为您的 UID 将已更改。

解决方法:

实际解决方案非常简单。你只需删除以前的 WiFi 配置(即使你显然没有足够的权限来正确连接它!)

// Find an existing network configuration with the SSID you're trying to connect to:
val configuration = wifiManager.configuredNetworks.firstOrNull { network -> network.SSID == "\"YOUR_SSID\"" }

// Remove the configuration
if (configuration != null) {
    wifiManager.removeNetwork(configuration.networkId)
}

现在您可以创建新的配置,连接到它,并执行(a)(b)并保持持久的网络连接。
我已经在Android问题跟踪器上提交了一个错误报告: https://issuetracker.google.com/issues/123896447

当我尝试按照您的建议删除网络时,removeNetwork() 返回 false,实际上并没有删除该网络。 - Keselme
由于这是一个错误,你遇到不同的行为并不奇怪。不幸的是,谷歌没有任何建议,我们只能期望在某些设备/平台上无法正常工作。 - Tim Malseed

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