简体   繁体   English

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

[英]After connecting to WiFi programmatically, disconnects a few seconds later

I am having an issue with switching wifi networks on the users behalf. 我遇到了代表用户切换wifi网络的问题。 We have an IoT device that we need to connect to in order to set it up. 我们有一个IoT设备需要连接才能进行设置。 Using the WifiManager and ConnectivityManager , I can make the connection and even make a REST call to it, but it changes back after about 10 seconds. 使用WifiManagerConnectivityManager ,我可以建立连接,甚至可以对它进行REST调用,但它会在大约10秒后恢复。 I don't understand why. 我不明白为什么。 There are a couple of strange log lines from the device that I am sure are related but I don't know how to fix, mainly: 设备中有一些奇怪的日志行我确定是相关的,但我不知道如何修复,主要是:

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

There is a lot about permissions in there, but I think I am asking for them all: 那里有很多关于权限的内容,但我想我要求所有权限:

<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" />

And I ask for the RuntimePermission for location since I am testing this on a device with SDK 27. What's more is that it does let me connect, but just changes it's mind few seconds later. 我要求RuntimePermission用于定位,因为我在带有SDK 27的设备上测试它。更重要的是它确实让我连接,但几秒钟之后就改变了它的想法。

The issue is caused when you try to scan for networks with WifiManager.startScan() since Android has changed its permission model. 当您尝试使用WifiManager.startScan()扫描网络时会导致此问题,因为Android已更改其权限模型。 You require to check for the runtime permission to access the coarse/fine location and you also have to check if the location provider (GPS) is switched ON. 您需要检查访问粗略/精确位置的运行时权限,还必须检查位置提供程序(GPS)是否已打开。 Otherwise you won't get any location updates. 否则,您将无法获得任何位置更新。 In your case, the location updates contain also wifi SSIDs, which you have scanned for. 在您的情况下,位置更新还包含您已扫描的wifi SSID。

Also note, that you have to check, if the user has NOT connected to that device previously via system settings, because it is not permitted by an app to connect to user defined access points from within an app. 另请注意,如果用户之前未通过系统设置连接到该设备,则必须检查,因为应用程序不允许从应用程序中连接到用户定义的访问点。 To allow the app to connect again in behalf of the user, the user must delete/forget that network in the system settings. 要允许应用程序代表用户再次连接,用户必须在系统设置中删除/忘记该网络。 If you don't check that, you will get an supplicant authentication error from the subsystem. 如果不进行检查,则会从子系统获得请求者身份验证错误。

Another notes to IoT Wifi devices: they are mostly "headless" access points, ie have no internet. IoT Wifi设备的另一个注意事项:它们大多是“无头”接入点,即没有互联网。 Many Android devices have the issue, that they require a valid captive portal. 许多Android设备存在问题,即它们需要有效的强制网络门户。 See this issue: https://android.stackexchange.com/questions/130265/stay-connected-to-specific-wifi-which-has-no-internet 请参阅此问题: https//android.stackexchange.com/questions/130265/stay-connected-to-specific-wifi-which-has-no-internet

To solve this issue, you must connect with a static IP address. 要解决此问题,您必须使用静态IP地址进行连接。 However, Android does not offer an API to set this programmatically. 但是,Android不提供以编程方式设置此API的API。 So you must use reflection as stated here: Set static IP and gateway programmatically in Android 6.x (Marshmallow) 因此,您必须使用此处所述的反射: 在Android 6.x(Marshmallow)中以编程方式设置静态IP和网关

I've had a similar experience when trying to connect to an existing WiFi configuration, and I found Denis' answer very helpful. 我尝试连接现有的WiFi配置时遇到了类似的经历,我发现Denis的回答非常有帮助。 The following represents my findings on a Nexus 5x running Android 8.1.0. 以下代表我对运行Android 8.1.0的Nexus 5x的调查结果。

When things work: 当事情有效:

In order to maintain a persistent connection to a WiFi network which doesn't have internet access, you either need to call: 为了保持与无法访问互联网的WiFi网络的持久连接,您需要致电:

  • (a) bindToProcess() on that network, which tells your app to route all of its traffic over this network despite the lack of internet connection, or (a)该网络上的bindToProcess() ,告诉您的应用程序尽管没有互联网连接, bindToProcess()通过此网络路由其所有流量,或者

  • (b) you can configure your HTTP client to use the desired network's socket factory. (b)您可以配置HTTP客户端以使用所需的网络套接字工厂。

If you do either of these with a WiFi configuration which your app created, the system doesn't disconnect you from the network due to lack of internet access. 如果您使用应用创建的WiFi配置执行其中任何一项操作,系统不会因为缺少互联网访问而断开您与网络的连接。

When they don't: 当他们不:

If the WiFi configuration you are trying to connect to was not created by your app (based on the app's UID), you are still able to connect, and you can perform (a) or (b) , but the system will disconnect you from that network after a short period of time. 如果您尝试连接的WiFi配置不是由您的应用程序创建的(基于应用程序的UID),您仍然可以连接,并且您可以执行(a)(b) ,但系统会断开您与那个网络在很短的时间之后。 This seems like an Android bug to me. 这对我来说似乎是一个Android错误。 The system allows you to connect to a configuration you didn't create, but will report the following: 系统允许您连接到未创建的配置,但会报告以下内容:

UID xxxxx does not have permission to update configuration

connectToUserSelectNetwork Allowing uid xxxxx with insufficient permissions to connect=16

Shortly after, it will disconnect you from your configured network, the exact same way it does if you don't perform (a) or (b) .. This seems like a bug in the implementation of whatever part of the Android system kicks you off a network for not having internet access. 不久之后,它将使您与配置的网络断开连接,就像您不执行(a)(b)时一样 。这似乎是执行Android系统的任何部分的一个错误踢你关闭网络没有互联网访问。 Either you shouldn't be able to connect to that network in the first place, or it should allow you to persist a connection using (a) or (b) . 您可能无法首先连接到该网络,或者应该允许您使用(a)(b)来保持连接。

The cases where a WiFi configuration is not considered to have been created by your app are both when the user manually configures that network via the system WiFi settings, or when you re-run the app in Android Studio. 当用户通过系统WiFi设置手动配置网络时,或者在Android Studio中重新运行应用程序时,您的应用程序不会认为已经创建了WiFi配置的情况。 So if you're debugging, and you configure a network, then re-run the app, you won't be able to maintain a persistent connection to that previously configured network, because your UID will have changed. 因此,如果您正在调试,并且配置网络,然后重新运行该应用程序,您将无法维持与先前配置的网络的持久连接,因为您的UID已经更改。

Solution : 方案

The actual solution is quite simple. 实际的解决方案非常简单。 You can just remove the previous WiFi configuration (even though you apparently don't have 'sufficient' permission to properly connect to it!) 你可以删除以前的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)
}

Now you can create a new configuration, connect to it, and perform (a) or (b) and maintain a persistent network connection. 现在,您可以创建新配置,连接到该配置,并执行(a)(b)并维护持久性网络连接。

I've filed a bug report on the Android Issue Tracker: https://issuetracker.google.com/issues/123896447 我已经在Android问题跟踪器上提交了错误报告: https//issuetracker.google.com/issues/123896447

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM