java - 为什么android(6.0)系统在深度 sleep 约1小时后禁止网络连接

标签 java android wifi

深度 sleep 一小时后,我无法使用 Android 的深度 sleep 模式。 该问题仅发生在 Android 6+ 上。在 Android <5 上不会出现此问题。未使用 Android 5 进行测试,因为没有可用的设备。

设备配置:
我有两台 Android 6 设备,Google Nexus 5 和 HTC One M9。 两个设备都配置为仅 Wifi(没有 sim 卡)并且 wifi 策略配置为始终开启(即使在 sleep 模式下)。

情况:
我有一个清醒的广播接收器,它在 AlarmManager.ELAPSED_REALTIME_WAKEUP 上注册,当应用程序进入后台时每 2 分钟触发一次。当应用程序暂停和释放时,如果应用程序进入前台,也会获取 wifi 锁。

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

接收者的工作很简单。他应该只调用一个 weburl(获取请求)。请求成功、超时或抛出异常后释放wakelock。

在 list 中,WAKE_LOCK 权限也存在。

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

日志显示1h后receiver也被调用,只是网络请求失败。

源代码示例:

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 hibernate 模式下运行,您需要采用此 https://developer.android.com/training/monitoring-device-state/doze-standby.html#assessing_your_app

最佳答案

but after ~1 hour the network request fails

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

Do you have an idea what is going wrong

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

请理解,添加 Doze 模式是专门为了防止开发人员执行您正在尝试执行的操作。每两分钟进行一次网络 I/O 对电池生命周期来说非常糟糕。太多开发者不关心用户和这些用户的电池,因此 Android 正在从这些开发者手中夺走控制权以帮助用户。

how to fix it?

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

现在,如果用户认为用户想让您的应用消耗更多电池,则用户可以将您的应用添加到电池优化白名单。这是在“设置”>“应用程序”>(操作栏中的齿轮图标)>“忽略电池优化”中。任何设置了“忽略电池优化”的应用都将表现得更像旧设备。

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

关于java - 为什么android(6.0)系统在深度 sleep 约1小时后禁止网络连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37210447/

相关文章:

java nio NoFilepatternException如何处理文件路径中的空格

java - 如何在javafx中为鼠标单击事件调用相同的方法并输入按键

android - 我的相机应用程序在打开时崩溃。

android - 如何使用 WiFi direct 将一部 Android 手机连接到多部其他 Android 手机,并且每部手机都使用单独的 channel ?

java - 如何更改 Eclipse 插件中的默认 IDetailPane?

java - 在构造函数中动态初始化数组 (Java)

java - 两个或多个安卓设备之间的 wifi 聊天

android - 如何只扫描(单播扫描)一个特定的 AP 而不是扫描信道?

java - 准备 MediaPlayer 播放自定义文件时出现问题

java - 整洁架构 : Combining Interactors