Checking Android’s Network Connectivity With Network Callback.

Evans Chepsiror
3 min readAug 8, 2020

At some point in time, as an Android engineer, one would need to maintain, or write a feature of an application that requires to connect to an online server or DB. To do this, we need to know if the user has an active internet connection before the network call is made for good User experience.

To achieve this, we’d use the following syntax;

private fun isNetworkAvailable(): Boolean {
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE)
return if (connectivityManager is ConnectivityManager) {
val networkInfo: N̶e̶t̶w̶o̶r̶k̶I̶n̶f̶o̶? = connectivityManager.̶a̶c̶t̶i̶v̶e̶N̶e̶t̶w̶o̶r̶k̶I̶n̶f̶o̶
networkInfo?.i̶s̶C̶o̶n̶n̶e̶c̶t̶e̶d̶ ?: false
} else false
}

But the problem is, now we see strike through on some code, meaning that this was deprecated with the introduction of API level 29. I know someone (I included) might think, ‘yes I can see a strike through, but, yes its working so its fine.’ The truth is, its deprecated because there’s a better way to achieve this.

Entered Network Callback in API level 21. And according to the documentation,

A class that answers queries about the state of network connectivity. It also notifies applications when network connectivity changes.

Now you get excited and wonder how do I refactor to make use of the network callback. First, we set up the network callback;

private val networkCallback = object :        ConnectivityManager.NetworkCallback() {

override fun onAvailable(network: Network) {
Variables.isNetworkConnected = true
}

override fun onLost(network: Network) {
Variables.isNetworkConnected = false
}
}

Then we actually register the callback; for android API level 24 and above;

cm.registerDefaultNetworkCallback(networkCallback)

and for API level 21 to 23;

cm.registerNetworkCallback(
builder.build(), networkCallback
)

As seen above, we have two methods, onAvailable() we are telling the callback to do these tasks when the network is available. And the opposite, if we lose a connection, is true for the onLost() method.

What this means is, our callback will listen to and notify us every time there’s a change with the network. How cool😎 is that. Then you might ask, ‘this is really great, but how do I get the current network state?’

To achieve this, I use of one of Kotlin’s Property Delegates. I found this article that expounds on Kotlin’s delegates. Here is a snippet;

This feature lets you create and implement properties once and use them anywhere. Delegation is a design pattern where object/property instead of performing a task, it delegates that task to another helper object.

And with that in mind, we will create a global variable with the following syntax

object Variables {
var isNetworkConnected: Boolean by Delegates.observable(false) { property, oldValue, newValue ->
Log.i("Network connectivity", "$newValue")
}
}

and back in our callback class we assign variables accordingly.

fun startNetworkCallback() {
val cm: ConnectivityManager =
application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val builder: NetworkRequest.Builder = NetworkRequest.Builder()

cm.registerNetworkCallback(
builder.build(),
object : ConnectivityManager.NetworkCallback() {

override fun onAvailable(network: Network) {
Variables.isNetworkConnected = true
}

override fun onLost(network: Network) {
Variables.isNetworkConnected = false
}
})
}

So to make use of our callbacks, we fire up the callback, preferably in the onCreate() of our Application class,

NetworkMonitor(this).startNetworkCallback()

and anywhere we need to check the network state we use the following syntax

Variables.isNetworkConnected

To stop the network callback, we use the following syntax;

fun stopNetworkCallback() {
val cm: ConnectivityManager =
application.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
cm.unregisterNetworkCallback(ConnectivityManager.NetworkCallback())
}

Remember that the network call back requires ACCESS_NETWORK_STATE permission.

That’s it. Now you can comfortably refactor. Not only do we get rid of the deprecated lines of code, but also we make use of the more powerful network callback.

Update

After further research, Thanks to @denisshov72, I have noticed that, there’s been an issue with this callback that seems to call the `onLost()` everytime the user switches capabilities from Cellular to Wi-Fi.

To fix this, in the network monitor use `defaultNetworkCallback()` for Android API 24 and above. I have updated the class accordingly both in the article and the Github project.

You can find the complete updated implementation in this project on GitHub.

--

--