How to Check for Internet Connection in Android using Kotlin

In this tutorial, I’m going to show you how to check the internet connection in your Android app without using any 3rd party library.

Adding required dependencies

Go to your app-level build.gradle file and add the following dependency:

// ... dependencies { // ... implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0' // ... }
Code language: Kotlin (kotlin)

The Local Broadcast Manager will help us to track the changes of internet connection (e.g, from Wi-Fi to cellular, or from Wi-Fi to no connection)

Next, go to the AndroidManifest.xml and add the following permission:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Code language: HTML, XML (xml)

Creating the NetworkMonitorUtil file

Create a new Kotlin file, and give it the name NetworkMonitorUtil.

Then, paste the following code inside:

enum class ConnectionType { Wifi, Cellular } class NetworkMonitorUtil(context: Context) { private var mContext = context private lateinit var networkCallback: NetworkCallback lateinit var result: ((isAvailable: Boolean, type: ConnectionType?) -> Unit) @Suppress("DEPRECATION") fun register() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { // Use NetworkCallback for Android 9 and above val connectivityManager = mContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager if (connectivityManager.activeNetwork == null) { // UNAVAILABLE result(false,null) } // Check when the connection changes networkCallback = object : NetworkCallback() { override fun onLost(network: Network) { super.onLost(network) // UNAVAILABLE result(false, null) } override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { super.onCapabilitiesChanged(network, networkCapabilities) when { networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> { // WIFI result(true,ConnectionType.Wifi) } else -> { // CELLULAR result(true,ConnectionType.Cellular) } } } } connectivityManager.registerDefaultNetworkCallback(networkCallback) } else { // Use Intent Filter for Android 8 and below val intentFilter = IntentFilter() intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE") mContext.registerReceiver(networkChangeReceiver, intentFilter) } } fun unregister() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { val connectivityManager = mContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager connectivityManager.unregisterNetworkCallback(networkCallback) } else { mContext.unregisterReceiver(networkChangeReceiver) } } @Suppress("DEPRECATION") private val networkChangeReceiver: BroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager val activeNetworkInfo = connectivityManager.activeNetworkInfo if (activeNetworkInfo != null) { // Get Type of Connection when (activeNetworkInfo.type) { ConnectivityManager.TYPE_WIFI -> { // WIFI result(true, ConnectionType.Wifi) } else -> { // CELLULAR result(true, ConnectionType.Cellular) } } } else { // UNAVAILABLE result(false, null) } } } }
Code language: Kotlin (kotlin)

Because some methods are deprecated in newer versions of Android we’re going to use two different ways to check the internet connection:

For devices with Android 9 (Pie) and above we use NetworkCallback, which has methods to detect when the network is available or not and what type is (Wifi, Cellular e.t.c).

And for devices with Android 8 (Oreo) and below, we use the method CONNECTIVITY_ACTION combine with LocalBroadcastManager to run the code whenever the network state changes.

Using NetworkMonitorUtil

To use the NetworkMonitorUtil, first, you have to initialize it and register the LocalBroadcastManager/NetworkCallback in the onResume() method:

class MainActivity : AppCompatActivity() { private val networkMonitor = NetworkMonitorUtil(this) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // ... } override fun onResume() { super.onResume() networkMonitor.register() } }
Code language: Kotlin (kotlin)

To get the state of the internet connection, use result:

override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // ... networkMonitor.result = { isAvailable, type -> runOnUiThread { when (isAvailable) { true -> { when (type) { ConnectionType.Wifi -> { Log.i("NETWORK_MONITOR_STATUS", "Wifi Connection") } ConnectionType.Cellular -> { Log.i("NETWORK_MONITOR_STATUS", "Cellular Connection") } else -> { } } } false -> { Log.i("NETWORK_MONITOR_STATUS", "No Connection") } } } } }
Code language: Kotlin (kotlin)

Note: If you have to do changes in the UI, your code needs to be inside a runOnUiThread { }

And to stop monitoring, unregister the LocalBroadcastManager/NetworkCallback in the onStop() method:

override fun onStop() { super.onStop() networkMonitor.unregister() }
Code language: Kotlin (kotlin)
You can find the final project here

If you have any questionsplease feel free to leave a comment below

Subscribe
Notify of
guest
15 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Am koemheang

Nice tutorial!! Thanks!!

Aswin

How to initialize :

lateinit var result: ((isAvailable: Boolean, type: ConnectionType?) -> Unit)
Aswin

For some reason I’m getting an error that result has not be initialized yet, I even copied all your code and tried.

Robin

How can I implement this into an Fragment instead of an Activity?

Robin

Much appreciated!

Sergey
 ConnectionType.Wifi -> {
          rootView.internet_status.text = "Wifi Connection"
 }

this block is triggered several times!!!!! Any solution????

Sergey

The question is why it is called several times? I use toast message and it is shown several times…

Sergey
override fun onAvailable(network: Network) {
    super.onAvailable(network)
    showToast("")
}

should use…Many thanks!!!!

Yasser AKBBACH

I tested this on my OPPO F9 device, somehow when I disable the Wi-Fi & enable it again that latter’s callback gets called multiple times, this doesn’t happen on Samsung or Huawei devices, so I fixed it to be like:

enum class ConnectionType {
    Wifi, Cellular
}

class NetworkMonitorUtil(context: Context) {

    private var mContext = context
    private var mState : ConnectionType? = null

    private lateinit var networkCallback: ConnectivityManager.NetworkCallback

    lateinit var result: ((isAvailable: Boolean, type: ConnectionType?) -> Unit)

    fun register() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            // Use NetworkCallback for Android 9 and above
            val connectivityManager = mContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

            if (connectivityManager.activeNetwork == null) {

                result(false,null) // UNAVAILABLE
            }

            // Check when the connection changes
            networkCallback = object : ConnectivityManager.NetworkCallback() {
                override fun onLost(network: Network) {
                    super.onLost(network)

                    mState = null
                    result(false, null) // UNAVAILABLE
                }

                override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
                    super.onCapabilitiesChanged(network, networkCapabilities)
                    when {
                        networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) && mState != ConnectionType.Wifi -> {
                            mState = ConnectionType.Wifi
                            result(true, mState)     // WIFI
                        }
                        networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) && mState != ConnectionType.Cellular -> {
                            mState = ConnectionType.Cellular
                            result(true, mState)     // CELLULAR
                        }
                    }
                }
            }
            connectivityManager.registerDefaultNetworkCallback(networkCallback)
        } else {
            // Use Intent Filter for Android 8 and below
            IntentFilter("android.net.conn.CONNECTIVITY_CHANGE").apply {
                mContext.registerReceiver(networkChangeReceiver, this)
            }
        }
    }

    fun unregister() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            val connectivityManager = mContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            connectivityManager.unregisterNetworkCallback(networkCallback)
        } else {
            mContext.unregisterReceiver(networkChangeReceiver)
        }
    }

    @Suppress("DEPRECATION")
    private val networkChangeReceiver : BroadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {

            val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val activeNetworkInfo = connectivityManager.activeNetworkInfo

            if (activeNetworkInfo != null) {
                // Get Type of Connection
                when (activeNetworkInfo.type) {
                    ConnectivityManager.TYPE_WIFI -> {
                        result(true, ConnectionType.Wifi)     // WIFI
                    }
                    else -> {
                        result(true, ConnectionType.Cellular) // CELLULAR
                    }
                }
            } else {
                result(false, null)                      // UNAVAILABLE
            }
        }
    }
}
Alfonso

Thanks for the post! It is working perfectly for wifi connection.
Although for Cellular connection is only detecting when mobile data option is off or on. But not if the device has access to internet through it.