Android : 在屏幕关闭的情况下进入覆盖区域后重新连接到 Wi-Fi [英] Android : Reconnect to Wi-Fi after entering coverage area while screen turned off

查看:24
本文介绍了Android : 在屏幕关闭的情况下进入覆盖区域后重新连接到 Wi-Fi的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力在设备处于接入点范围内时自动打开 Wi-Fi 而无需打开屏幕.测试和找出解决方案非常令人沮丧,尤其是因为不同的设备有完全不同的结果.

I have been struggling with automatically turning on Wi-Fi as soon as the device is within range of an access point without turning on the screen. It has been very frustrating to test and figure out a solution, especially since different devices have completely different results.

基础测试
在此测试期间保持屏幕关闭.该应用程序应持有 WifiLock.

Base Test
Keep the screen turned off during this test. The application should hold a WifiLock.

  1. 走出 WiFi 覆盖范围并在那里停留一分钟.
  2. 回到报道中.

结果:Wifi 没有立即重新连接,因此应用程序不会重新连接到服务器.根据设备和设置的不同,有时在屏幕打开之前它根本不会重新连接.

Result : The Wifi is not reconnected immediately and thus app does not reconnect to server. Depending on the device and settings, sometimes it would not reconnect at all until the screen was turned on.

强制重新连接 Wi-Fi
好的,这次我的应用程序会在 Wifi 断开连接的情况下每隔一段时间调用 WifiManager.Reconnect().

Forcing the Wi-Fi to reconnect
Ok, this time my application calls WifiManager.Reconnect() at an interval if Wifi is disconnected.

重复测试.结果:适用于 S3,不适用于其他设备.

Repeated the test. Results : Worked for the S3, failed for other devices.

尝试添加一些其他调用
尝试了 WifiManager.Scan()、WifiManager.Reassociate() 等的不同组合.最终它适用于除 S4 之外的大多数设备(HTC、S3).

Tried adding some other calls
Tried different combinations of WifiManager.Scan(), WifiManager.Reassociate(), ...etc. Eventually it was working for most devices(HTC, S3) except the S4.

似乎适用于所有设备的代码

NetworkInfo wifiInfo = _androidConnectivityMgr.GetNetworkInfo(ConnectivityType.Wifi);
if (!_wifiManager.IsWifiEnabled || _wifiManager.WifiState == WifiState.Disabled || _wifiManager.WifiState == WifiState.Disabling)
{
    // Make sure the Wi-Fi is enabled, required for some devices when enable WiFi does not occur immediately
    _wifiManager.SetWifiEnabled(true);
}

if (!wifiInfo.IsConnectedOrConnecting)
{
    // Do not wait for the OS to initiate a reconnect to a Wi-Fi router
    _wifiManager.PingSupplicant();
    if (_wifiManager.WifiState == WifiState.Enabled)
    {
        try
        {
            // Brute force methods required for some devices
            _wifiManager.SetWifiEnabled(false);
            _wifiManager.SetWifiEnabled(true);
        }
        catch (Java.Lang.SecurityException)
        {
            // Catching exception which should not occur on most devices. OS bug details at :
            // https://code.google.com/p/android/issues/detail?id=22036
        }
    }
    _wifiManager.Disconnect();
    _wifiManager.StartScan();
    _wifiManager.Reassociate();
    _wifiManager.Reconnect();
}

我什至不确定所有这些代码都是必要的,因为我无法在网上找到很多信息.WifiFixer 确实有帮助一些.但这似乎适用于我测试过的设备.

I am not even sure all this code is necessary as I was unable to find much information online. WifiFixer did help some. But this does seem to work for the devices I have tested on.

问题

  • 有没有更好的方法来做到这一点?
  • 制造商是否真的修改了基本 Android,我可以看到如此大的差异?
  • 这完全是错误的处理方式吗?

感谢您阅读所有这些:)

Thanks for reading through all this :)

附加说明

  1. 代码在从 AlarmManager 启动的 10 秒以上的时间间隔内运行.WakeLock 仅在此通话期间保持.
  2. 在这个看起来很吓人的解决方案/黑客之前,Wifi 睡眠策略"影响了结果.这让我很困惑,因为我一直拿着 WifiLock,我认为这相当于从不".
  3. 以编程方式更改Wifi 睡眠策略"对 S4 不起作用,其他人可以确认吗?
  4. 是的,我们有这样做的特殊需要,并且知道电池的影响.

推荐答案

在该地区转了一圈.虽然上述解决方案确实适用于我们所有合格的设备,但有太多可能是不必要的调用.另外,我们得到了解决方案不起作用的新设备.这是一个更好的解决方案:

Had a second go around in the area. While the above solution did work for all our qualified devices, there were too many calls that might have been unnecessary. Plus we got new device for which the solution did not work. Here is a much better solution:

在每个时间间隔调用此代码

NetworkInfo wifiInfo = _androidConnectivityMgr.GetNetworkInfo(ConnectivityType.Wifi);
if (!wifiInfo.IsConnectedOrConnecting)
{
    // Need to make sure the CPU does not go to sleep before the following async calls are finished
    _wifiScanWakeLock.Acquire();

    // Do not wait for the OS to initiate a reconnect to a Wi-Fi router
    _wifiManager.StartScan();
}

  • _wifiScanWakeLock 只是一个部分的、非引用计数的 WakeLock,在 OnDestroy 中处理
  • Wi-Fi 扫描完成后

    private void OnWifiScanResultsReceived(Intent result)
    {
        NetworkInfo wifiInfo = _androidConnectivityMgr.GetNetworkInfo(ConnectivityType.Wifi);
        if (!wifiInfo.IsConnectedOrConnecting)
        {
            Dictionary<string, int> savedNetworks = new Dictionary<string, int>();
            foreach (WifiConfiguration config in _wifiManager.ConfiguredNetworks)
            {
                string escapedSsid = Regex.Replace(config.Ssid, "^"|"$", String.Empty);
                savedNetworks[escapedSsid] = config.NetworkId;
            }
    
            foreach (ScanResult ap in _wifiManager.ScanResults)
            {
                int networkId;
                if (savedNetworks.TryGetValue(ap.Ssid, out networkId))
                {
                    savedNetworks.Remove(ap.Ssid);
                    _wifiManager.EnableNetwork(networkId, false);
                }
            }
        }
        _wifiScanWakeLock.Release();
    }
    

    • WifiConfiguration 的 BSSID 始终为 null,不能用于与 ScanResult 的 BSSID 进行唯一比较
    • 这是核心代码,显然你必须担心两个相同的 SSID 和其他优化的情况
    • 这篇关于Android : 在屏幕关闭的情况下进入覆盖区域后重新连接到 Wi-Fi的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆