以编程方式连接到WiFi后,几秒钟后断开连接

Joe*_*hea 6 android

我遇到了代表用户切换wifi网络的问题.我们有一个IoT设备需要连接才能进行设置.使用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
Run Code Online (Sandbox Code Playgroud)

那里有很多关于权限的内容,但我想我要求所有权限:

<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" />
Run Code Online (Sandbox Code Playgroud)

我要求RuntimePermission用于定位,因为我在带有SDK 27的设备上测试它.更重要的是它确实让我连接,但几秒钟之后就改变了它的想法.

Den*_*Loh 6

WifiManager.startScan()由于 Android 已更改其权限模型,因此当您尝试使用以下方式扫描网络时会导致该问题。您需要检查访问粗略/精细位置的运行时权限,还必须检查位置提供程序 (GPS) 是否已打开。否则,您将不会获得任何位置更新。在您的情况下,位置更新还包含您已扫描的 wifi SSID。

另请注意,您必须检查用户之前是否未通过系统设置连接到该设备,因为应用程序不允许从应用程序内连接到用户定义的接入点。要允许应用程序代表用户再次连接,用户必须在系统设置中删除/忘记该网络。如果您不检查,您将收到来自子系统的请求者身份验证错误。

IoT 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)


Tim*_*eed 5

我在尝试连接到现有 WiFi 配置时也有过类似的经历,我发现 Denis 的回答非常有帮助。以下是我对运行 Android 8.1.0 的 Nexus 5x 的发现。

当一切正常时:

为了保持与无法访问 Internet 的 WiFi 网络的持久连接,您需要调用:

  • (a)bindToProcess()在该网络上,它告诉您的应用程序在缺乏互联网连接的情况下通过该网络路由其所有流量,或者

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

如果您使用应用程序创建的 WiFi 配置执行上述任一操作,系统不会因缺乏互联网访问而断开您与网络的连接。

当他们不这样做时:

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

UID xxxxx does not have permission to update configuration

connectToUserSelectNetwork Allowing uid xxxxx with insufficient permissions to connect=16
Run Code Online (Sandbox Code Playgroud)

不久之后,它会断开你与配置的网络的连接,就像你不执行(a)(b)时的情况一样。这似乎是 Android 系统任何部分的实现中的一个错误。由于无法访问互联网而关闭网络。要么您一开始就无法连接到该网络,要么它应该允许您使用(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)
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以创建新配置,连接到它,然后执行(a)(b)并维护持久的网络连接。

我已在 Android 问题跟踪器上提交了错误报告: https://issuetracker.google.com/issues/123896447