Android, better Internet connection monitoring with Kotlin Flow

What do we want? We want to create Internet connection tracker that is backed by Kotlin Flow . We want to display to the user that there is no internet connection, to retry our requests as soon as internet is available etc.

Our job here is to create NetworkStatusTracker that will help us do what we talked about above, learn new things and have fun doing it.

For the start need class to represent network status. Let’s call it…. NetworkStatus :

This is straightforward.

Now we are going for the main thing: NetworkStatusTracker .

Let’s list our requirements:

  1. We want to have information about network status.
  2. We want status to be updated when network status changes, not to check(poll) it every time.
  3. We want to reuse it and make it versatile.

Here we go!

First we need to find a way to access network information. We do it using ConnectivityManager system service. There are two parts to this:
1st obtaining ConnectivityManager and 2nd registering callbacks for network updates.

We obtain it like this:

Now we need to register callbacks for network status updates:

Now we are going to introduce Flow so we can observe changes. For that we will use callbackFlow Flow builder. Like so:

We have added quite a few changes here so let’s take a step back and see what have we done.

We have built Flow with callbackFlow builder function that takes lambda as a parameter and inside that lambda we decide what Flow will emit using offer() method. callbackFlow is Channel backed Flow . On respective callbacks we offer values to the Flow , NetworkStatus.Unavailable or NetworkStatus.Available .
On line 24 we register callbacks and we have to unregister those same callbacks and we do it inside awaitClose {} block, line 26–28. awaitClose {} is called when Channel is either closed or cancelled. We already said that callbackFlow is using Channel underneath.
You can also see map extension function that helps us avoid type checks with when or if . We can also create flatMap extension same way we have done with map but I leave it up to you. I have it in full example gist linked at the end but if you are not sure how to do it I encourage you to do it by yourself.

Let’s use what we’ve built!

We have our ViewModel and state that we will observe inside our Activity

I will not bother you with dependency injection frameworks and libraries so am doing it all vanilla style.

If you run the app you can see that it works as intended.

Our solution has one problem tho. When we turn off Airplane mode and look in our logcat we see two onAvailable prints. Why is that?
We emit Available every time network connection is available but our Wi-Fi and mobile data are both in that category so when any of them becomes available we emit Available . First we register mobile data is available and we fire Available and right after our Wi-Fi is available so we fire Available once again. There are many ways how we can tackle this problem. We can create Set and put Network we get from callback in that set monitor values in that set, implement counter etc. I will leave this up to you. You can also ping the network to check will it work before emitting Available .

I hope here you learned something new and interesting. You can find full example here ->

Post any questions/suggestions/mistakes you’ve found in the comments!

Best of luck and stay healthy.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store