javaandroidandroid-connectivitymanagernetworkinfo

Getting "BLOCKED" network state when Android's data saver is off


I am developing an app to be used on a specific tablet running Android 7.0. I'm using a Service to send periodic DatagramPackets. I can only use mobile networks. I check the connectivity status using ConnectivityManager, NetworkInfo and DetailedState. I get the network state with this code:

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
DetailedState networkState = activeNetwork.getDetailedState();

In my tablet the Data Saver is off. Just in case, I have run tests to verify there are no restrictions when the screen turns off, cm.getRestrictBackgroundStatus() always returns 1, which is RESTRICT_BACKGROUND_STATUS_DISABLED, even when the network is blocked.

So, why is the network blocked? Do my app need special permissions? Do my tablet need special configuration?


Solution

  • In order to give a complete solution I will answer my question.

    why is the network blocked?

    As the documentation provided by Stanislav Kireev pointed, this BLOCKED network state happens because the device is in Doze. This device state does not allow internet access starting from Android 6.0 (API level 23).

    But the documentation also says that "the system provides a configurable whitelist of apps that are partially exempt from Doze and App Standby optimizations". For more detailed explanation you can read Support for other use cases section. You can add your app to the whitelist from code or configuring the system.

    Do my app need special permissions?

    If you need to add your app to the whitelist from code, you need to add a permission in the manifest file:

    <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
    

    And add this code to your activity:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        String packageName = getPackageName();
        PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
        if (!pm.isIgnoringBatteryOptimizations(packageName)) {
            Intent intent = new Intent();
            intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
            intent.setData(Uri.parse("package:" + packageName));
            startActivity(intent);
        }
    }
    

    I got this solution from this answer.

    Do my tablet need special configuration?

    If you want, you can add your app from Settings > Battery > 3 dots > Battery optimisation. Choose All apps in the pick list, select your app and choose Don’t optimise option.

    I got this solution from this answer (it has more detailed explanation).