为什么android(6.0)系统在深度睡眠约1小时后会绕网络连接

时间:2016-05-13 12:46:08

标签: java android wifi wlan

深度睡眠一小时后,我在安卓的深度睡眠模式下遇到了麻烦。 这个问题只发生在Android 6+上。在Android< 5上,问题不会发生。未经Android 5测试,因为没有设备可用。

设备配置:
我有两个Android 6设备,谷歌Nexus 5和HTC One M9。 两种设备都配置为仅Wifi(没有SIM卡),并且wifi策略配置为alyways on(即使在睡眠模式下)。

情况:
我有一个唤醒的广播接收器,当应用程序进入后台时,它会在AlarmManager.ELAPSED_REALTIME_WAKEUP上注册,每2分钟触发一次。如果应用程序到达前台,那么当应用程序暂停并释放时,无线锁定是准确的。

由于Android KitKat AlarmManager.setRepeating(...)不稳定,在Android 6上我使用AlarmManager.setWindow(...),窗口只有1秒。
每次接收器触发时,接收器(PendingIntent)都会重新注册。

接收器工作简单。他应该只调用weburl(获取请求)。在请求成功,超时或抛出异常后释放唤醒锁。

在清单中,WAKE_LOCK权限也存在。

问题:
当我将应用程序置于后台(接收器变为启用状态)然后关闭屏幕时,接收器每2分钟正确调用一次,但在约1小时后网络请求失败。

日志显示接收器也在1小时后被调用,只有网络请求失败。

源代码示例:

public class TestTools {
    private static final String LOG_TAG = TestTools.class.getSimpleName();

    public static String excuteGet(String targetURL) {
        try {
            URL obj = new URL(targetURL);
            HttpURLConnection con = (HttpURLConnection) obj.openConnection();
            con.setRequestMethod("GET");
            con.setConnectTimeout(10*1000);
            con.setReadTimeout(5*1000);

            int responseCode = con.getResponseCode();
            Log.d(LOG_TAG, "GET Response Code :: " + responseCode);

            if (responseCode == HttpURLConnection.HTTP_OK) { // success
                BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
                String inputLine;
                StringBuilder response = new StringBuilder();

                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
                in.close();

                // print result
                Log.d(LOG_TAG, response.toString());

                return response.toString();
            } else {
                Log.d(LOG_TAG, String.format("GET request not worked (response code :: %s)", responseCode));
            }
        }
        catch (ProtocolException e) {
            Log.d(LOG_TAG, "ProtocolException: " + e.getMessage());
        }
        catch (MalformedURLException e) {
            Log.d(LOG_TAG, "MalformedURLException: " + e.getMessage());
        }
        catch (IOException e) {
            Log.d(LOG_TAG, "IOException: " + e.getMessage());
        }

        return null;
    }

}

public class Receiver extends WakefulBroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        Log.d(LOG_TAG, "onReceive");

        final Thread test = new Thread(new Runnable() {
            @Override
            public void run() {
                TestTools.excuteGet("http://www.google.de/");
            }
        });
        test.start();

        try {
            test.join();
        } catch (InterruptedException e) {
            Log.d(LOG_TAG, e.getMessage());
        }

        // here the receiver is reregistered

        WakefulBroadcastReceiver.completeWakefulIntent(intent);
    }
}

你知道出了什么问题以及如何解决它吗?


更新:要使应用处理Android打盹模式,您需要采用此https://developer.android.com/training/monitoring-device-state/doze-standby.html#assessing_your_app

1 个答案:

答案 0 :(得分:6)

  

但是大约1小时后网络请求失败

据推测,该设备进入了Doze mode

  

你知道出了什么问题

从用户的角度来看,从Android的角度来看,没有任何问题。一切都按预期工作。

请理解,专门添加了打盹模式,以防止开发人员执行您尝试执行的操作。每两分钟进行一次网络I / O对电池寿命来说太糟糕了。太多开发人员不关心用户和那些用户的电池,因此Android正在控制那些开发人员,以帮助用户。

  

如何解决?

在很大程度上,没有什么可以解决的。同样,一切都按照规范工作。您可能需要调整您的期望。

现在,如果用户认为用户希望允许您的应用消耗更多电量,则用户可以将您的应用添加到电池优化白名单中。这是在设置>应用> (动作栏中的齿轮图标)> “忽略电池优化”。任何“忽略电池优化”设置的应用都会更像旧设备。

也欢迎用户将设备放在充电器上;充电时,设备不会进入打盹模式。