【问题标题】:How do I keep Wifi from disconnecting when phone is asleep?手机睡着了,怎么让wifi不掉线?
【发布时间】:2014-03-13 04:48:52
【问题描述】:

我有一项服务,它会以一定的时间间隔轮询服务器。我使用 AlarmManager 和 BroadcastReceiver 来启动服务。我的问题是,经过一段时间后,即使 Wifi 仍然启用,但由于某种原因,我的应用程序无法联系服务器。我收到“无法访问的网络”错误。

请注意,我已经获得了部分唤醒锁和 wifilock。

这是我的广播接收器代码。

public class ServiceAlarmBroadcastReceiver extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        WakeLock wakeLock = null;
        WifiLock wifiLock = null;
        try {
            PowerManager pm = (PowerManager) context
                    .getSystemService(Context.POWER_SERVICE);

            // acquire a WakeLock to keep the CPU running
            wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                    "MyWakeLock");
            if(!wakeLock.isHeld()){
                wakeLock.acquire();
            }

            Log.i("ServiceAlarmBroadcastReceiver", "WakeLock acquired!");


            WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            wifiLock = wm.createWifiLock(WifiManager.WIFI_MODE_FULL , "MyWifiLock");
            if(!wifiLock.isHeld()){
                wifiLock.acquire();
            }

            Log.i("ServiceAlarmBroadcastReceiver", "WifiLock acquired!");
            context.startService(new Intent(context, ThePollerService.class));
        } finally {
            // release the WakeLock to allow CPU to sleep
            if (wakeLock != null) {
                if (wakeLock.isHeld()) {
                    wakeLock.release();
                    Log.i("ServiceAlarmBroadcastReceiver", "WakeLock released!");
                }
            }

            // release the WifiLock
            if (wifiLock != null) {
                if (wifiLock.isHeld()) {
                    wifiLock.release();
                    Log.i("ServiceAlarmBroadcastReceiver", "WiFi Lock released!");
                }
            }
        }
    }
}

【问题讨论】:

  • 您如何确定问题出在 WiFi 连接进入休眠状态。 “无法访问网络”消息可能有其他原因。您是否观看了连接广播,或使用WifiManager 检查了 WiFi 状态或其他任何东西来证实您的理论?

标签: android


【解决方案1】:

此处发布的代码的问题是您从接收器内部获取和释放 WakeLock 和 WifiLock。除非您在服务的 onStart 内完成整个任务(如果是,为什么还要费心提供服务???),锁将在您的轮询任务完成之前被释放。

我建议将您的实现更改为以下内容:

  1. 让广播接收器启动服务(仅此而已)
  2. 让服务获取唤醒锁并启动线程来执行轮询操作。最合适的位置是您的服务 onCreate)
  3. 轮询操作完成后,您应该停止轮询服务
  4. 在您的服务的 onDestroy 中,您应该释放您在 onStart 中获得的锁

【讨论】:

  • 好的,假设我每 6 小时收集一次。在该时间间隔内,设备可能处于睡眠模式且 Wifi 关闭。当我请求 wifi 的 WAKE_LOCK 时,在 onStart 时,它会启用 wifi 对吗?但是由于Wifi需要几秒钟才能连接到接入点,我的服务会无法连接到互联网吗?
  • 如果用户禁用了Wifi,它不会因为你获得锁而重新连接。否则,您可以等到活动网络再次连接,然后再尝试连接您的服务。 WiFi 应该不需要很长时间就可以准备好,因为它在睡眠模式下没有完全断开连接。事实上,我不确定 ConnectivityManager 在这种情况下是否会报告其未连接。
  • 嗨贾斯汀,我认为有一个很好的解决方案,是注册一个 BroadcastReceiver 来检测何时建立 wifi 连接,然后检查最后一次下载是否早于 12 小时(我的池间隔),如果是,它将下载。
【解决方案2】:

感谢汤姆,我能够解决这个问题。代码如下:

Settings.System.putInt(getContentResolver(),
  Settings.System.WIFI_SLEEP_POLICY, 
  Settings.System.WIFI_SLEEP_POLICY_NEVER);

【讨论】:

  • 这实际上看起来很糟糕 - 电池方面。将您的 wifi 锁移动到您的服务实现中怎么样?您的服务是 WakefulIntentService 吗?您在接收器中获得的唤醒锁不会起到太大作用
  • 以上代码需要以下权限:
  • 请注意,自 API 17 起已弃用此功能。请参阅 stackoverflow.com/a/18790243
【解决方案3】:

在 WiFi 设置、菜单键、高级选项下,有 WIFI_SLEEP_POLICY 选项列表,当设置为从不时,手机睡眠时 WiFi 连接会保持打开状态。

您可以在 Settings.System Package 下进行操作。

http://developer.android.com/reference/android/provider/Settings.System.html#WIFI_SLEEP_POLICY

希望这会有所帮助,

汤姆

【讨论】:

  • 感谢汤姆的回复。您如何实际更改此设置?
  • 不建议更改用户的设置。您应该等待释放唤醒/wifilocks,直到您的工作完成。
【解决方案4】:

对 javauser 的回答稍作修改:

private void setNeverSleepPolicy() {
        try {
            ContentResolver cr = getContentResolver();
            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
                int set = android.provider.Settings.System.WIFI_SLEEP_POLICY_NEVER;
                android.provider.Settings.System.putInt(cr, android.provider.Settings.System.WIFI_SLEEP_POLICY, set);
            } else {
                int set = android.provider.Settings.Global.WIFI_SLEEP_POLICY_NEVER;
                android.provider.Settings.System.putInt(cr, android.provider.Settings.Global.WIFI_SLEEP_POLICY, set);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

【讨论】:

  • 不建议更改用户的设置。您应该等待释放唤醒/wifilocks,直到您的工作完成。
猜你喜欢
  • 1970-01-01
  • 2016-09-12
  • 1970-01-01
  • 2013-12-23
  • 1970-01-01
  • 2020-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多