Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: Internet connectivity change listener

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.

like image 350
Confuse Avatar asked Sep 05 '14 03:09

Confuse


People also ask

How do I manage Internet connection on Android?

Restart your device. Open your Settings app and tap Network & internet or Connections. Depending on your device, these options may be different. Turn Wi-Fi off and mobile data on, and check if there's a difference. If not, turn mobile data off and Wi-Fi on and check again.

How does Android determine Internet connection?

Android devices detect captive portals requesting a specific URL, that currently is http://connectivitycheck.gstatic.com/generate_204. If they receive a 204 response then there's connectivity. If they receive a 30x response, then there's a captive portal in the way.

How do I check permissions on Android internet?

Step 1 − Create a new project in Android Studio, go to File ⇒ New Project and fill all required details to create a new project. Step 2 − To find the internet status we have to add network state permission to AndroidManifest. xml file as shown below.

How do I get to network state?

Getting instantaneous state getActiveNetwork(); With a reference to a network, your app can query information about it. NetworkCapabilities caps = connectivityManager. getNetworkCapabilities(currentNetwork);


9 Answers

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!

like image 61
Cjames Avatar answered Oct 07 '22 17:10

Cjames


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         }     }) } 
like image 21
bmjohns Avatar answered Oct 07 '22 15:10

bmjohns


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);
}
like image 28
algrid Avatar answered Oct 07 '22 16:10

algrid


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);
like image 26
Silvia H Avatar answered Oct 07 '22 17:10

Silvia H


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);
    }
}
like image 28
Manuel Schmitzberger Avatar answered Oct 07 '22 17:10

Manuel Schmitzberger


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

private boolean isNetworkConnected() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    if (!(cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected())) {
        //Do something
        return false;
    }
    return true;
}

And also add this permission in your Android Manifest.xml

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
like image 20
Lakpriya Senevirathna Avatar answered Oct 07 '22 16:10

Lakpriya Senevirathna


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

        }
    }
}
like image 22
Waris Ali Rehmani Avatar answered Oct 07 '22 16:10

Waris Ali Rehmani


Hello from the year 2022.

In my custom view model I observe network status changes like this:

public class MyViewModel extends AndroidViewModel {
    private final MutableLiveData<Boolean> mConnected = new MutableLiveData<>();

    public MyViewModel(Application app) {
        super(app);

        ConnectivityManager manager = (ConnectivityManager)app.getSystemService(Context.CONNECTIVITY_SERVICE);

        if (manager != null && 
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

            NetworkRequest networkRequest = new NetworkRequest.Builder()
                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                .build();

            manager.registerNetworkCallback(networkRequest, new ConnectivityManager.NetworkCallback() {
                public void onAvailable(@NonNull Network network) {
                    mConnected.postValue(true);
                }

                public void onLost(@NonNull Network network) {
                    mConnected.postValue(false);
                }

                public void onUnavailable() {
                    mConnected.postValue(false);
                }
            });
        } else {
            mConnected.setValue(true);
        }
    }

    @NonNull
    public MutableLiveData<Boolean> getConnected() {
        return mConnected;
    }
}

And then in my Activity or Fragment I can change the UI by observing:

@Override
protected void onCreate(Bundle savedInstanceState) {
    MyViewModel vm = new ViewModelProvider(this).get(MyViewModel.class);

    vm.getConnected().observe(this, connected -> {
        // TODO change GUI depending on the connected value
    });
}
like image 20
Alexander Farber Avatar answered Oct 07 '22 17:10

Alexander Farber


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)
like image 39
Ibrahim Ali Avatar answered Oct 07 '22 15:10

Ibrahim Ali