Android event for internet connectivity state change [duplicate]
Asked Answered
W

4

61

I am making an app where a user is uploading information and files to my server on a somewhat frequent basis. This is done in new threads through a dedicated uploader service.

I know from this thread

Detect whether there is an Internet connection available on Android

that you can check if there is an internet connection relatively easily. You can also get socketTimeoutExceptions to detect internet connectivity issues. All that is well and good, and lets me cache my uploads easily enough when the connection didn't work for whatever reason.

My question though is how do I know when to reattempt the upload? Is there an event triggered when the connection is restored? Or am I stuck making a new thread that sleeps and then checks internet connectivity every 30 seconds or something?

Any ideas would be appreciated!

Weiweibel answered 29/5, 2011 at 16:56 Comment(0)
P
126

very old post but i would like to share my receiver

no need to put your hands on manifest or other boring resources :)

USAGE

YOUR ACTIVITY:

/*
 * You need to implement NetworkStateReceiverListener.
 * This interface is described inside the NewtworkStateReceiver class
 */
public class MyActivity implements NetworkStateReceiverListener {
    /* ... */
    private NetworkStateReceiver networkStateReceiver;
}

IN YOUR ACTIVITY: INSTANTIATE THE RECEIVER

public void onCreate(Bundle savedInstanceState) {
    /* ... */
    networkStateReceiver = new NetworkStateReceiver();
    networkStateReceiver.addListener(this);
    this.registerReceiver(networkStateReceiver, new IntentFilter(android.net.ConnectivityManager.CONNECTIVITY_ACTION));
}

public void onDestroy() {
    super.onDestroy();
    networkStateReceiver.removeListener(this);
    this.unregisterReceiver(networkStateReceiver);
}

IN YOUR ACTIVITY: IMPLEMENTS THE REQUIRED METHODS

@Override
public void networkAvailable() {
    Log.d("tommydevall", "I'm in, baby!");
    /* TODO: Your connection-oriented stuff here */
}

@Override
public void networkUnavailable() {
    Log.d("tommydevall", "I'm dancing with myself");
    /* TODO: Your disconnection-oriented stuff here */        
}

THE RECEIVER

just copy and paste into your project as NetworkStateReceiver.java

public class NetworkStateReceiver extends BroadcastReceiver {

    protected Set<NetworkStateReceiverListener> listeners;
    protected Boolean connected;

    public NetworkStateReceiver() {
        listeners = new HashSet<NetworkStateReceiverListener>();
        connected = null;
    }

    public void onReceive(Context context, Intent intent) {
        if(intent == null || intent.getExtras() == null)
            return;

        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo ni = manager.getActiveNetworkInfo();

        if(ni != null && ni.getState() == NetworkInfo.State.CONNECTED) {
            connected = true;
        } else if(intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,Boolean.FALSE)) {
            connected = false;
        }

        notifyStateToAll();
    }

    private void notifyStateToAll() {
        for(NetworkStateReceiverListener listener : listeners)
            notifyState(listener);
    }

    private void notifyState(NetworkStateReceiverListener listener) {
        if(connected == null || listener == null)
            return;

        if(connected == true)
            listener.networkAvailable();
        else
            listener.networkUnavailable();
    }

    public void addListener(NetworkStateReceiverListener l) {
        listeners.add(l);
        notifyState(l);
    }

    public void removeListener(NetworkStateReceiverListener l) {
        listeners.remove(l);
    }

    public interface NetworkStateReceiverListener {
        public void networkAvailable();
        public void networkUnavailable();
    }
}

ENJOY ;)

Piaffe answered 16/9, 2014 at 16:6 Comment(8)
Hello i tried your code but i cannot seem to get the receiver to be called when there is no internet. The one for internet networkAvailable() gets called though but not the one for no network...Xyster
Figured it out. Its to do with android 5 not recognising ConnectivityManager.EXTRA_NO_CONNECTIVITY - #29678352Xyster
Shouldn't you also call unregisterReceiver(networkStateReceiver); in the activity's onDestroy() method?Heidy
Why no one else includes this fundamental line? _ this.*registerReceiver*(networkStateReceiver, new IntentFilter(android.net.ConnectivityManager.CONNECTIVITY_ACTION));_Uncommitted
Don't forget to add the corresponding permission to the manifest file: <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />Taste
you are never unregistering the receiver, which keeps a hard reference to the activity. A lot of leaking in perspectiveUllrich
This doesn't seem to work on my case. I am sorry. :(Leucopenia
what if i use your method and then on disconnected state it show a new activity in which it shows no internet and a retry option on which it rechecks the internet connectivityCai
D
30

If you just want to do something simple when the connectivity changes, there is a much easier solution.

In your activity, create a Broadcast Receiver:

private BroadcastReceiver networkStateReceiver=new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo ni = manager.getActiveNetworkInfo();
        doSomethingOnNetworkChange(ni);
    }
};

Then in onResume and onPause do the registration:

@Override
public void onResume() {
    super.onResume();
    registerReceiver(networkStateReceiver, new IntentFilter(android.net.ConnectivityManager.CONNECTIVITY_ACTION));
}

@Override
public void onPause() {
    unregisterReceiver(networkStateReceiver);
    super.onPause();
}
Demers answered 12/7, 2016 at 10:19 Comment(3)
Thank you. Can you please explain what is the difference between your solution and using a broadcastReceiver registered in the manifest?Precarious
@JCarlos Basically, if you declare it in the manifest, then it will be fired application-wise, every time the connectivity changes. If you use a Receiver defined in the Activity as seen here, then it will only fire when your Activity is running.Demers
From far best answer, some people here don't know that receiver cost a lot in performanceSpartan
K
14

Not quite sure what was going on in Tommaso's broadcast receiver but it wasn't working for me, here's my implementation. It only notifies on change between connectivity available/unavailable.

Also I register it in onResume() and unregister in onPause(). Otherwise it's the same as above.

public class NetworkStateReceiver extends BroadcastReceiver {

    private ConnectivityManager mManager;
    private List<NetworkStateReceiverListener> mListeners;
    private boolean mConnected;

    public NetworkStateReceiver(Context context) {
        mListeners = new ArrayList<NetworkStateReceiverListener>();
        mManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        checkStateChanged();
    }

    public void onReceive(Context context, Intent intent) {
        if (intent == null || intent.getExtras() == null)
            return;

        if (checkStateChanged()) notifyStateToAll();
    }

    private boolean checkStateChanged() {
        boolean prev = mConnected;
        NetworkInfo activeNetwork = mManager.getActiveNetworkInfo();
        mConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
        return prev != mConnected;
    }

    private void notifyStateToAll() {
        for (NetworkStateReceiverListener listener : mListeners) {
            notifyState(listener);
        }
    }

    private void notifyState(NetworkStateReceiverListener listener) {
        if (listener != null) {
            if (mConnected) listener.onNetworkAvailable();
            else listener.onNetworkUnavailable();
        }
    }

    public void addListener(NetworkStateReceiverListener l) {
        mListeners.add(l);
        notifyState(l);
    }

    public void removeListener(NetworkStateReceiverListener l) {
        mListeners.remove(l);
    }

    public interface NetworkStateReceiverListener {
        public void onNetworkAvailable();

        public void onNetworkUnavailable();
    }
}
Kuo answered 27/11, 2014 at 17:24 Comment(2)
With all respect, I tried your solution and found Tommaso's worked better.Jiggermast
How does it work better? Just curious before I try one of these solutions.Basset
R
11

Android Nougat & O (API 24+) - Network State

Changes mades to @darnmason answer (constructor) to make it work on API 24+.

public NetworkStateReceiver(Context context) {
    mListeners =  new ArrayList<>();
    mManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
    context.registerReceiver(NetworkStateReceiver.this, intentFilter);

    checkStateChanged();
}
Riddell answered 11/7, 2017 at 10:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.