10

I am using this piece of code to detect Internet connection state changes. It works fine on Android<5.0, but on API 21 this:

intent.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY)

is always false. How to make this code to work on Android 5.0?

My BroadcastReceiver:

public class NetworkStateReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        if(intent.getExtras()!=null) {
            final ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
            final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
            if(networkInfo != null && networkInfo.isConnectedOrConnecting()) {
                Log.d("receiver test", "detected on");
            }
        }
        Log.d("receiver test", Boolean.toString(intent.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY)));
        if(intent.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE)) {
            Log.d("receiver test", "detected off");
        }
    }
}
fragon
  • 3,391
  • 10
  • 39
  • 76

1 Answers1

22

You can use NetworkRequest added in API level 21.

Create a custom intent action:

public static final String CONNECTIVITY_ACTION_LOLLIPOP = "com.example.CONNECTIVITY_ACTION_LOLLIPOP";

Create the new method registerConnectivityActionLollipop:

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void registerConnectivityActionLollipop() {

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
        return;

    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkRequest.Builder builder = new NetworkRequest.Builder();

    connectivityManager.registerNetworkCallback(builder.build(), new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network) {
            Intent intent = new Intent(CONNECTIVITY_ACTION_LOLLIPOP);
            intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);

            sendBroadcast(intent);
        }

        @Override
        public void onLost(Network network) {
            Intent intent = new Intent(CONNECTIVITY_ACTION_LOLLIPOP);
            intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);

            sendBroadcast(intent);
        }
    });
}

Add the new intent action to the intent filter and call registerConnectivityActionLollipop:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
intentFilter.addAction(CONNECTIVITY_ACTION_LOLLIPOP);

registerReceiver(mBroadcastReceiver, intentFilter);
registerConnectivityActionLollipop();

Change the BroadcastReceiver to support the new intent action:

private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && TextUtils.equals(intent.getAction(), ConnectivityManager.CONNECTIVITY_ACTION) ||
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && TextUtils.equals(intent.getAction(), CONNECTIVITY_ACTION_LOLLIPOP)) {

            if (intent.getExtras() != null) {
                final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
                final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
                if (networkInfo != null && networkInfo.isConnectedOrConnecting()) {
                    Log.d("receiver test", "detected on");
                }
            }

            Log.d("receiver test", Boolean.toString(intent.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY)));
            if (intent.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE)) {
                Log.d("receiver test", "detected off");
            }
        }
    }
};
Mattia Maestrini
  • 32,270
  • 15
  • 87
  • 94
  • 1
    Thank you. I had to modify your solution a little bit to suit my needs, but it gave me an overal idea on how to fix the problem with Android 5.0 – fragon Apr 20 '15 at 13:32
  • 1
    @MattiaMaestrini:Isn't your code reversed? Shouldn't it be `intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);` in the `onAvailable`? – Jim Feb 08 '16 at 10:14
  • 2
    @Jim You are right. Thanks for pointing that out, I just fixed the answer. – Mattia Maestrini Feb 08 '16 at 10:20
  • 2
    So basically the idea is that we re-raise the intent so that the code that works ok in the previous SDKs can work in 21+ right? But why not just handle it in the `registerConnectivityActionLollipop`? We already would check for which SDK we are running – Jim Feb 08 '16 at 10:29
  • 1
    I am trying your code. The `onAvailable` and `onLost` are called but when I check the `intent.getAction()` it is always `android.net.conn.CONNECTIVITY_CHANGE` and not a `com.example.CONNECTIVITY_ACTION_LOLLIPOP` – Jim Feb 08 '16 at 13:31
  • 1
    OMG it is so tiresome. I vehemntly oppose copy pasting but eversince I started android I have to copy paste solution on this site. Pathetic. – Neon Warge Feb 14 '17 at 02:45