76

I already have this code which listens to connectivity change -

public class NetworkStateReceiver extends BroadcastReceiver
{
  public void onReceive(Context context, Intent intent)
  {
    Log.d("app","Network connectivity change");

    if(intent.getExtras() != null)
    {
      NetworkInfo ni = (NetworkInfo) intent.getExtras().get(ConnectivityManager.EXTRA_NETWORK_INFO);
      if(ni != null && ni.getState() == NetworkInfo.State.CONNECTED)
      {
        Log.i("app", "Network " + ni.getTypeName() + " connected");
      }
    }

    if(intent.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE))
    {
      Log.d("app", "There's no network connectivity");
    }
  }
}

And I check Internet connectivity using this code - Internet Check

But the problem is that if network suddenly loses internet connection without any connectivity change, this code is useless. Is there any way to create Broadcast Receiver listener for Internet connectivity change? I have a web app and sudden Internet connectivity changes can cause problems.

Community
  • 1
  • 1
Confuse
  • 4,968
  • 6
  • 31
  • 57
  • refer to this https://stackoverflow.com/questions/15698790/broadcast-receiver-for-checking-internet-connection-in-android-app – lenhuy2106 Jan 18 '18 at 21:35

10 Answers10

99

Try this

public class NetworkUtil {
    public static final int TYPE_WIFI = 1;
    public static final int TYPE_MOBILE = 2;
    public static final int TYPE_NOT_CONNECTED = 0;
    public static final int NETWORK_STATUS_NOT_CONNECTED = 0;
    public static final int NETWORK_STATUS_WIFI = 1;
    public static final int NETWORK_STATUS_MOBILE = 2;

    public static int getConnectivityStatus(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        if (null != activeNetwork) {
            if(activeNetwork.getType() == ConnectivityManager.TYPE_WIFI)
                return TYPE_WIFI;

            if(activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE)
                return TYPE_MOBILE;
        } 
        return TYPE_NOT_CONNECTED;
    }

    public static int getConnectivityStatusString(Context context) {
        int conn = NetworkUtil.getConnectivityStatus(context);
        int status = 0;
        if (conn == NetworkUtil.TYPE_WIFI) {
            status = NETWORK_STATUS_WIFI;
        } else if (conn == NetworkUtil.TYPE_MOBILE) {
            status = NETWORK_STATUS_MOBILE;
        } else if (conn == NetworkUtil.TYPE_NOT_CONNECTED) {
            status = NETWORK_STATUS_NOT_CONNECTED;
        }
        return status;
    }
}

And for the BroadcastReceiver

public class NetworkChangeReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(final Context context, final Intent intent) {

        int status = NetworkUtil.getConnectivityStatusString(context);
        Log.e("Sulod sa network reciever", "Sulod sa network reciever");
        if ("android.net.conn.CONNECTIVITY_CHANGE".equals(intent.getAction())) {
            if (status == NetworkUtil.NETWORK_STATUS_NOT_CONNECTED) {
                new ForceExitPause(context).execute();
            } else {
                new ResumeForceExitPause(context).execute();
            }
       }
    }
}

Don't forget to put this into your AndroidManifest.xml

 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 <uses-permission android:name="android.permission.INTERNET" />
 <receiver
        android:name="NetworkChangeReceiver"
        android:label="NetworkChangeReceiver" >
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            <action android:name="android.net.wifi.WIFI_STATE_CHANGED" />
        </intent-filter>
    </receiver>

Hope this will help you Cheers!

Cjames
  • 1,742
  • 19
  • 23
  • 9
    why would you need to check if (!"android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) ???? – shridutt kothari Apr 02 '15 at 12:04
  • @shriduttkothari I use it for downloading functionality – Cjames May 04 '16 at 13:28
  • :@Cjames But "android.intent.action.BOOT_COMPLETED" does not have anything to do with downloading functionality or Network connectivity, so i think it's irrrelevant in the above code. isn't it? – shridutt kothari May 04 '16 at 15:15
  • 2
    It is not working in gionee s plus device.......any other way to do this ? – himCream Dec 03 '16 at 06:43
  • 2
    This works well except for one problem. I'm also trying to have a listener for the LAN/Ethernet connection to my Android TV Box. This works great for WiFi or Mobile connections, but not for LAN connection. I have this code that checks the state of the LAN connection, but I need a listener to catch any changes in the internet state, not just the WiFi or Mobile network: `code` NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting(); `code` – Wayne Johnson May 03 '17 at 16:26
  • 39
    Registering a receiver like this in your Manifest to receive connectivity change events will no longer work on Android 7.0+ https://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html#MonitorChanges – w3bshark Jul 17 '17 at 17:43
  • 1
    Found a special case for network connectivity saying there is no internet but actually there is. It turns out `getActiveNetworkInfo` will always return you **DISCONNECTED/BLOCKED** in a specific case when network is changed while battery level is low and app was just switched Check out this post: https://stackoverflow.com/questions/34884442/android-checking-network-connectivity-return-not-connected-when-connected-to-wi/45231746#45231746 – Phil Jul 21 '17 at 07:51
  • 1
    i cant find ForceExitPause and ResumeForceExitPause – Pouria Hemati Apr 06 '19 at 11:33
  • you can register the receiver just directly at your activity. On destroy, don't forget to unregister again! – larsaars Apr 25 '20 at 13:16
55

ConnectivityAction is deprecated in api 28+. Instead you can use registerDefaultNetworkCallback as long as you support api 24+.

In Kotlin:

val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
connectivityManager?.let {
    it.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            //take action when network connection is gained
        }
        override fun onLost(network: Network?) {
            //take action when network connection is lost
        }
    })
}
bmjohns
  • 5,324
  • 1
  • 29
  • 37
44

Update:

Apps targeting Android 7.0 (API level 24) and higher do not receive CONNECTIVITY_ACTION broadcasts if they declare the broadcast receiver in their manifest. Apps will still receive CONNECTIVITY_ACTION broadcasts if they register their BroadcastReceiver with Context.registerReceiver() and that context is still valid.

You need to register the receiver via registerReceiver() method:

 IntentFilter intentFilter = new IntentFilter("android.net.conn.CONNECTIVITY_CHANGE");
 mCtx.registerReceiver(new NetworkBroadcastReceiver(), intentFilter);
Silvia H
  • 6,977
  • 5
  • 29
  • 33
  • I'm not getting my broadcast receiver called even with this code on 8.0. – TheRealChx101 Feb 02 '19 at 01:11
  • @TheRealChx101, if the context is still valid you should be good to go. What context have you used? – Tomer Petel Feb 20 '19 at 07:30
  • @TheRealChx101 The `"android.net.conn.CONNECTIVITY_CHANGE"` string is actually the `CONNECTIVITY_ACTION` constant. As you'll see at https://developer.android.com/reference/android/net/ConnectivityManager#CONNECTIVITY_ACTION , this constant was deprecated in API 28. Could your problem be to do with that? – ban-geoengineering Apr 17 '19 at 18:58
36

Here's the Java code using registerDefaultNetworkCallback (and registerNetworkCallback for API < 24):

ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(Network network) {
        // network available
    }

    @Override
    public void onLost(Network network) {
        // network unavailable
    }
};

ConnectivityManager connectivityManager =
        (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    connectivityManager.registerDefaultNetworkCallback(networkCallback);
} else {
    NetworkRequest request = new NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();
    connectivityManager.registerNetworkCallback(request, networkCallback);
}
algrid
  • 4,204
  • 2
  • 24
  • 31
  • 1
    `NetworkRequest` requires minimum API level 21. What can we do for API level 19? – Aliton Oliveira Dec 11 '19 at 16:38
  • does this be added in broadcast receiver? it does register the callback, so I am confused. – A_rmas Aug 25 '20 at 18:26
  • @AlitonOliveira Unless you have a reason to keep supporting API 19, I would really advise dropping support for APIs below 21, Since (according to Google) 94.1% of Android users are on API 21 and above. Also, API 21 is a really sweet spot for a lot of newer APIs you'll be surprised how much unnecessary code for backwards compatibility you'll remove from your codebase. – Heysem Katibi Mar 03 '21 at 21:39
  • @algrid I would like to confirm this works on physical device, but on emulator does not. When connection is lost on emulator, onAvaiable is triggered also. – I.Step May 20 '21 at 15:17
30

This should work:

public class ConnectivityChangeActivity extends Activity {

    private BroadcastReceiver networkChangeReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d("app","Network connectivity change");
        }
    };

    @Override
    protected void onResume() {
        super.onResume();

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(networkChangeReceiver, intentFilter);
    }

    @Override
    protected void onPause() {
        super.onPause();

        unregisterReceiver(networkChangeReceiver);
    }
}
Manuel Schmitzberger
  • 3,715
  • 1
  • 27
  • 37
3
  1. first add dependency in your code as implementation 'com.treebo:internetavailabilitychecker:1.0.4'
  2. implements your class with InternetConnectivityListener.
public class MainActivity extends AppCompatActivity implements InternetConnectivityListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        InternetAvailabilityChecker.init(this);
        mInternetAvailabilityChecker = InternetAvailabilityChecker.getInstance();
        mInternetAvailabilityChecker.addInternetConnectivityListener(this);
    }

    @Override
    public void onInternetConnectivityChanged(boolean isConnected) {
        if (isConnected) {
            alertDialog = new AlertDialog.Builder(this).create();
            alertDialog.setTitle(" internet is connected or not");
            alertDialog.setMessage("connected");
            alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    });
            alertDialog.show();

    }
    else {
            alertDialog = new AlertDialog.Builder(this).create();
            alertDialog.setTitle("internet is connected or not");
            alertDialog.setMessage("not connected");
            alertDialog.setButton(AlertDialog.BUTTON_NEUTRAL, "OK",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }
                    });
            alertDialog.show();

        }
    }
}
Kiran Maniya
  • 5,637
  • 4
  • 34
  • 53
2

I used this method as a connection listener. Working for Lolipop+, Android JAVA language.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkRequest networkRequest = new NetworkRequest.Builder().build();
            connectivityManager.registerNetworkCallback(networkRequest, new ConnectivityManager.NetworkCallback() {
                @Override
                public void onAvailable(Network network) {
                    super.onAvailable(network);
                    Log.i("Tag", "active connection");
                }

                @Override
                public void onLost(Network network) {
                    super.onLost(network);
                    Log.i("Tag", "losing active connection");
                    isNetworkConnected();
                }
            });
        } 

And also add this permission in your Android Manifest.xml

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

I have noticed that no one mentioned WorkManger solution which is better and support most of android devices.

You should have a Worker with network constraint AND it will fired only if network available, i.e:

val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
val worker = OneTimeWorkRequestBuilder<MyWorker>().setConstraints(constraints).build()

And in worker you do whatever you want once connection back, you may fire the worker periodically .

i.e:

inside dowork() callback:

notifierLiveData.postValue(info)
Ibrahim Ali
  • 961
  • 5
  • 18
-2

This my implementation which you can providing in application scope:

class NetworkStateHelper @Inject constructor(
        private val context: Context
) {
    private val cache: BehaviorSubject<Boolean> = BehaviorSubject.create()

    private val receiver = object : BroadcastReceiver() {
        override fun onReceive(c: Context?, intent: Intent?) {
            cache.onNext(isOnlineOrConnecting())
        }
    }

    init {
        val intentFilter = IntentFilter()
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
        context.registerReceiver(receiver, intentFilter)
        cache.onNext(isOnlineOrConnecting())
    }

    fun subscribe(): Observable<Boolean> {
        return cache
    }

    fun isOnlineOrConnecting(): Boolean {
        val cm = context.applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val netInfo = cm.activeNetworkInfo
        return netInfo != null && netInfo.isConnectedOrConnecting
    }
}

I used this rxjava and dagger2 libraies

Harco
  • 323
  • 3
  • 14
-3

implementation 'com.treebo:internetavailabilitychecker:1.0.1'

public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        InternetAvailabilityChecker.init(this);
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        InternetAvailabilityChecker.getInstance().removeAllInternetConnectivityChangeListeners();
    }
}
Lennoard Silva
  • 466
  • 1
  • 5
  • 15
Hans Cruz
  • 1
  • 1