anargund
anargund

Reputation: 3249

How can I receive a notification when the device loses network connectivity?

I know you can write code through which you can determine whether the device is connected to a network.

But in my app what I want to do is get a notification if the device changes its state from 'network' to 'no network'. This would happen, for example, when the user travels into a tunnel and loses signal, etc. Or when on WiFi, the user goes out of range of the access point and no longer has access to the internet.

Does the Android API provide something where you can register a listener so that you get notified every time there is a change in network state?

I found this code and tried to use it, but it does not do anything. I don't get any notifications when the network state changes.

public class ConnectivityManager extends PhoneStateListener{

Activity activity;
public ConnectivityManager(Activity a){
    TelephonyManager telephonyManager = (TelephonyManager)a.getSystemService(Context.TELEPHONY_SERVICE);
    telephonyManager.listen(this, PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
    activity = a;
}

@Override
public void onDataConnectionStateChanged(int state) {
    super.onDataConnectionStateChanged(state);
    switch (state) {
    case TelephonyManager.DATA_DISCONNECTED:
        new AlertDialog.Builder(activity).
        setCancelable(false).
        setTitle("Connection Manager").
        setMessage("There is no network connection. Please connect to internet and start again.").
        setNeutralButton("Ok", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int whichButton) {
                System.exit(0);
            }
        }).create();
        break;

    case TelephonyManager.DATA_CONNECTED:
        break;
    }
}
}

Also, I have added the appropriate permissions in AndroidManifest.xml:

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

Upvotes: 31

Views: 35933

Answers (7)

Konstantin Konopko
Konstantin Konopko

Reputation: 5422

You can easily use Merlin and his beard. Here you can also get a type of connection: mobile or wifi.

implementation 'com.novoda:merlin:1.2.0'

private MerlinsBeard merlinsBeard;

private NetworkChecker(Context context){

    Merlin merlin = new Merlin.Builder()
            .withConnectableCallbacks()
            .withDisconnectableCallbacks()
            .build(context);

    merlinsBeard = new MerlinsBeard.Builder().build(context);

    merlin.registerConnectable(() -> {
        Timber.d("Connection enabled");
    });

    merlin.registerDisconnectable(() -> {
        Timber.d("Connection disabled");
    });

    merlin.bind();
}


public boolean getConnected(){
    return merlinsBeard.isConnected();
}

Upvotes: 0

Varun Chandran
Varun Chandran

Reputation: 671

If you are trying to do that in Kotlin. Use this

   val isInternetWorking: Boolean by lazy {
        var success = false
        try {
            val url = URL("https://google.com")
            val connection = url.openConnection() as HttpURLConnection
            connection.connectTimeout = 10000
            connection.connect()
            success = connection.responseCode === 200
        } catch (e: IOException) {
            e.printStackTrace()
        }

        return@lazy success
    }

Do this in a thread.

Upvotes: 0

user3829854
user3829854

Reputation: 235

I implemented this feature by polling ConnectivityManager.

_connectivityManager = (ConnectivityManager)getSystemService(CONNECTIVITY_SERVICE);

Once we have a connectivity manager just poll it every now and then to see if you are still connected

private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
final Runnable networkStatusChecker = new Runnable() {
    public void run() {
        NetworkInfo activeNetwork = _connectivityManager.getActiveNetworkInfo();
        boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
        if(!isConnected) {
            System.out.println("disconnected from network");
            networkCheckerHandle.cancel(true);
        }
    }
};
final ScheduledFuture networkCheckerHandle = scheduler.scheduleAtFixedRate(networkStatusChecker, 10, 10, SECONDS);

Upvotes: 1

Mahendra Liya
Mahendra Liya

Reputation: 13218

The accepted answer didn't work for me (my tablet was connected to WiFi - no 3G). The following code worked for me:

public class ConnectivityChangeReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        System.out.println("*** Action: " + intent.getAction());
        if(intent.getAction().equalsIgnoreCase("android.net.conn.CONNECTIVITY_CHANGE")) {
            Toast.makeText(context, "Connection changed", Toast.LENGTH_SHORT).show();
        }
    }
}

and the change to AndroidManifest.xml

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

<receiver android:name=".custom.ConnectivityChangeReceiver">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
</receiver>

Upvotes: 9

Zahid Ansari
Zahid Ansari

Reputation: 192

myTelephonyManager=(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);

callStateListener = new PhoneStateListener(){
    public void onDataConnectionStateChanged(int state){
        switch(state){
        case TelephonyManager.DATA_DISCONNECTED:
            Log.i("State: ", "Offline");
            // String stateString = "Offline";
            // Toast.makeText(getApplicationContext(),
            // stateString, Toast.LENGTH_LONG).show();
            break;
        case TelephonyManager.DATA_SUSPENDED:
            Log.i("State: ", "IDLE");
            // stateString = "Idle";
            // Toast.makeText(getApplicationContext(),
            // stateString, Toast.LENGTH_LONG).show();
            break;
        }
    }       
};                      
myTelephonyManager.listen(callStateListener,
            PhoneStateListener.LISTEN_DATA_CONNECTION_STATE); 

Upvotes: 16

Geobits
Geobits

Reputation: 22342

You might want to consider using a BroadcastReceiver for ConnectivityManager.CONNECTIVITY_ACTION instead. From the docs:

A change in network connectivity has occurred. A connection has either been established or lost. The NetworkInfo for the affected network is sent as an extra; it should be consulted to see what kind of connectivity event occurred.

This receiver works for both WiFi and cellular data connectivity, unlike PhoneStateListener.LISTEN_DATA_CONNECTION_STATE, which will only notify you for changes in cellular networks.

Upvotes: 25

Bryan
Bryan

Reputation: 6699

Not sure if this will help but this looks similar...

Upvotes: 1

Related Questions