ErdnussFlipS ErdnussFlipS - 9 days ago 7
Android Question

Why the android (6.0) system forbit a network connection after ~1 hour in deep sleep

I have trouble with android's deep sleep mode after one hour in deep sleep.
The problem only occures on Android 6+. On Android <5 the problem does not occure. Not tested with Android 5, because no device is available.

Device configuration:

I have two Android 6 devices, Google Nexus 5 and HTC One M9.
Both devices are configured as Wifi only (without sim card) and wifi policy is configured as alyways on (even in sleep mode).

The situation:

I have a wakeful broadcast receiver, that is registered on AlarmManager.ELAPSED_REALTIME_WAKEUP to fire every 2 minutes, when the application goes in background. Also the wifi lock is accuired, when the application is paused and released, if the application comes to foreground.

Since Android KitKat AlarmManager.setRepeating(...) is inexat, on Android 6 I use AlarmManager.setWindow(...) with a window of only 1 second.

Everytime the receiver triggers, the receiver (PendingIntent) is reregistered again.

The receiver has a simple job. He should only call a weburl (get request). The wakelock is released after the request is successful, timed out or an exception is thrown.

In the manifest, the WAKE_LOCK permission also exists.

The problem:

When I put the application in background (receiver becomes enabled) and then turn off the screen, the receiver is called correctly every 2 minutes, but after ~1 hour the network request fails.

The log shows that the receiver is called also after 1h, only the network request fails.

Source code example:


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);
}
}


Do you have an idea what is going wrong and how to fix it?



Update: To make app working with Android doze mode, you need to adopt this https://developer.android.com/training/monitoring-device-state/doze-standby.html#assessing_your_app

Answer

but after ~1 hour the network request fails

Presumably, the device went into Doze mode.

Do you have an idea what is going wrong

From the standpoint of the user, and from the standpoint of Android, nothing is going wrong. Everything is working as expected.

Please understand that Doze mode was added specifically to prevent developers from doing what it is that you are trying to do. Doing network I/O every two minutes is terrible for battery life. Too many developers do not care about users and those users' batteries, and so Android is taking control away from those developers, to help the users.

how to fix it?

To a large extent, there is nothing to fix. Again, everything is working in accordance to specifications. You may need to adjust your expectations.

Now, if the user thinks that the user wants to allow your app to consume more battery, the user can add your app to battery optimization whitelist. This is in Settings > Apps > (gear icon in action bar) > "Ignore battery optimizations". Any app for which "ignore battery optimizations" is set will behave more like older devices.

The user is also welcome to keep their device on a charger; while charging, the device will not go into Doze mode.