Android

Monitor network connectivity change for available and lost in android app

As we all know that Google is providing very frequently version update for Android devices. Currently, Google has released the android Q a new version OS for android. Most of the people are still using the lower version of Android OS like Lollipop, marshmallow, Oreo, and Nougat because our hardware is not capable to take the upgrade for a newer version.

In every new version of OS, Google has updated the new security restriction like avoiding to use the implicit broadcast or static broadcast, background services blocked by Doze mode for battery optimization and removing few default permission for user application like SMS and many more. So its kind of headache for an android developer to maintain the application for all API version.

Avoid using Implicit Broadcast

So in this tutorial, we are going to check what is the best way of checking the network connectivity while the application is live. As I have explained in the above line that static broadcast is not going to work in android N because of holding the resource by static broadcast causing leaks. Till the Android L, we used the below static broadcast which we defined in Android Manifest.xml file.

<receiver android:name="com.namepackage.NetworkReceiver">
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
    </intent-filter>
</receiver>

Any object which is holding the resource for a long time is not a good approach in android. As we all know that android is providing a very limited memory of an application. Android framework has always given the first priority for a current application which is running by a user. During any time if the device is faced the memory low, then Android resource will kill the other applications which are in the stack and during the same time if any object holding the resource is causing the memory leaks.

As in the above code, we can see that registering the Broadcast Reciever as an implicit and now in new versions like android O and N, it is restricted to use. So what we need to do, we can use the explicit Broadcast Reciever for register and unregister to avoid the leaks.

Explicit Broadcast

we can use the dynamic broadcast which scop will be limited in that class only while static broadcast scop will be though out the application unnecessary holding resource for others class and View. To avoid the leaks, please unregister the broadcast when the View is inactive or detached.

// register 
registerReceiver(networkReceiver, new IntentFilter(AppConstants.CONNECTIVITY_ACTION));

// unregister
unregisterReceiver(networkReceiver);
class NetworkReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(AppConstants.CONNECTIVITY_ACTION)) {
          // update the connection
        }
    }
}

Now, Google has provided the new API in a new version which is called NetworkCallback in ConnectivityManager class.

Start using ConnectivityManager.NetworkCallback

In this API Google has removed to use any static or dynamic broadcast for monitoring the network change. But the process of a register and unregister network callback will be the same to avoid leaks.

// register the default network callback for N
connectivityManager.registerDefaultNetworkCallback(networkCallback);

 // register the default network callback for lowe version of N      
connectivityManager.registerNetworkCallback(networkRequest, networkCallback);
     
//unregister the network callback
 connectivityManager.unregisterNetworkCallback(networkCallback);

So here Android is recommended to use the network callback for lollipop onwards to the better result. This class has method override for network available and lost.

  class NetworkCallback extends ConnectivityManager.NetworkCallback {

        @Override
        public void onAvailable(Network network) {
            // network change is available
        }

        @Override
        public void onLost(Network network) {
            // network is lost
        }
    }

Use Live Data for Observing the change.

As we know that Live Data is a data holder class which is observing the change of an object. The best part of the Live Data is that it is aware of the Life cycle event of View.

connectionStateMonitor.observe(this, new Observer<Boolean>() {
            @Override
            public void onChanged(Boolean aBoolean) {
                
            }
        });

Live Data is proving the override method for a view is an active and inactive state. When the View is in an active state we will register the broadcast and when it is inactive we will unregister the broadcast to avoid the unnecessary the holding the resource. A view can get the update regarding the status change of network connectivity easily.

    @Override
    protected void onActive() {
        super.onActive();
       // register the broadcast here
    }

    @Override
    protected void onInactive() {
        super.onInactive();
       // unregister the broadcast here
    }

Let me put all code together to handle all the API version for all devices. We can use the Live Data for observing the change in the Network.

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.os.Build;

import androidx.lifecycle.LiveData;

public class ConnectionStateMonitor extends LiveData<Boolean> {

    private Context mContext;
    private ConnectivityManager.NetworkCallback networkCallback = null;
    private NetworkReceiver networkReceiver;
    private ConnectivityManager connectivityManager;

    public ConnectionStateMonitor(Context context) {
        mContext = context;
        connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            networkCallback = new NetworkCallback(this);
        } else {
            networkReceiver = new NetworkReceiver();
        }
    }

    @Override
    protected void onActive() {
        super.onActive();
        updateConnection();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            connectivityManager.registerDefaultNetworkCallback(networkCallback);

        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            NetworkRequest networkRequest = new NetworkRequest.Builder()
                    .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                    .build();
            connectivityManager.registerNetworkCallback(networkRequest, networkCallback);
        } else {
            mContext.registerReceiver(networkReceiver, new IntentFilter(AppConstants.CONNECTIVITY_ACTION));
        }
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            connectivityManager.unregisterNetworkCallback(networkCallback);
        } else {
            mContext.unregisterReceiver(networkReceiver);
        }
    }

    class NetworkCallback extends ConnectivityManager.NetworkCallback {

        private ConnectionStateMonitor mConnectionStateMonitor;

        public NetworkCallback(ConnectionStateMonitor connectionStateMonitor) {
            mConnectionStateMonitor = connectionStateMonitor;
        }

        @Override
        public void onAvailable(Network network) {
            if (network != null) {
                mConnectionStateMonitor.postValue(true);
            }
        }

        @Override
        public void onLost(Network network) {
            mConnectionStateMonitor.postValue(false);
        }
    }

    private void updateConnection() {
        if (connectivityManager != null) {
            NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
            if (activeNetwork != null && activeNetwork.isConnectedOrConnecting()) {
                postValue(true);
            }else{
                postValue(false);
            }
        }

    }

    class NetworkReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(AppConstants.CONNECTIVITY_ACTION)) {
                updateConnection();
            }
        }
    }
}

Great. Now let’s observe the change of the Network for updating the View.

ConnectionStateMonitor connectionStateMonitor = new ConnectionStateMonitor(getActivity());
connectionStateMonitor.observe(this, new Observer<Boolean>() {
    @Override
    public void onChanged(Boolean aBoolean) {
        if (aBoolean){
           // network availale
        }else{
          // network lost
        }
    }
});

I used this StackOverflow as a reference which is available in Kotlin Version. I am really thankful of Amokrane Chentir for the good suggestion.

Wrapping 

Now we have a good understanding of the network callback for monitoring the network connectivity change and live data for observing the change for View. In my next tutorial, we will learn a few more technical stuff, till then enjoy your healthy day.

If you are wondering to learn Android then Please learn from Android category and wondering to learn Kotlin then Kotlin Category will help you. If you want to learn all the python article, then learn from the python category.

Please do subscribe your email to get the newsletter on this blog on below and if you like this post then do not forget to share like and comment on the below section.

Happy Coding 🙂

 

4.9 7 votes
Article Rating

Recent Posts

Hide your production API key or any sensitive data in Android

Hi everyone, In this article, we are going to learn how to hide the production… Read More

2 years ago

How to handle the localisation or multi language support in android with examples?

Hello everyone, Today in this article, we are going to learn about localisation to support… Read More

2 years ago

How to convert any callback to Coroutines and use them in Kotlin Android?

Hello everyone, In this article, we are going to learn something to handle the callback… Read More

2 years ago

Request Permission Launcher with Kotlin in Android

In this article, we are learning about the run time permissions for request permission launchers.… Read More

2 years ago

Implement the SMS User Consent API and SMS Retriever API in Android

Hello everyone. In my last tutorial, we learned about the Jetpack Compose introduction and about applying the… Read More

3 years ago

Jetpack Compose Coroutine flow with LiveData/ViewModel in Android

Hello everyone, In this article, we are going to learn about the Jetpack Compose with… Read More

3 years ago