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

时间:2018-02-12 15:25:04

标签: 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

那里有许多关于权限的内容,但我认为我要求所有权限:

<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的设备上对此进行测试。更重要的是它 让我连接,但几秒后就改变它了。< / p>

2 个答案:

答案 0 :(得分:4)

当您尝试使用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的API。因此,您必须使用此处所述的反射:Set static IP and gateway programmatically in Android 6.x (Marshmallow)

答案 1 :(得分:2)

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

工作正常:

为了维持与无法访问Internet的WiFi网络的持久连接,您需要致电:

  • (a)bindToProcess()在该网络上,它告诉您的应用程序尽管没有Internet连接也通过该网络路由其所有流量,或者

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

如果您使用您的应用程序创建的WiFi配置来执行上述任一操作,则由于缺少Internet访问,系统不会断开您与网络的连接。

当他们不这样做时:

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

UID xxxxx does not have permission to update configuration

connectToUserSelectNetwork Allowing uid xxxxx with insufficient permissions to connect=16

不久之后,它将断开您与配置的网络的连接,与不执行(a)(b)时的操作完全相同。这似乎是在实施Android系统任何部分的过程中出现的一个错误,导致您因为无法访问Internet而被踢出网络。首先,您要么不能连接到该网络,要么可以使用(a)(b)来保持连接。< / p>

当用户通过系统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 Issue Tracker上提交了错误报告: https://issuetracker.google.com/issues/123896447

相关问题