In this blog, I’ll show how to check internet connection in android programmatically. While we are developing a professional app, you may need to check internet available or not. For example, while you are calling APIs you may need to check internet connection several times in an app. In this example, we’ll learn how we can check internet connections any place and anywhere.
I’m going to create a demo application, This app will automatically detect the internet changes using an internet connection listener. For the demonstration, I’ll create a sample app that app will capable of continuously check internet connection with android. So let started.
Create Android Project
Let move to Android Studio, and create a fresh project with some default template. We are going to use java 1.8 stuff in our project so lets set java version in app build.gradle file
compileOptions { sourceCompatibility = 1.8 targetCompatibility = 1.8 } kotlinOptions { jvmTarget = JavaVersion.VERSION_1_8.toString() }
Add ACCESS_NETWORK_STATE permission in Manifest
For detecting network permission we required some permission so let open the AndroidManifest and add below permission.
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Write a ConnectivityProvider interface
I’m going to write complete solution for check internet connection for pre and post LOLLIPOP devices solution in a single interface. Please have a look
package com.detectnetworkchange.connectivity.base import android.content.Context import android.content.Context.CONNECTIVITY_SERVICE import android.net.ConnectivityManager import android.net.NetworkCapabilities import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET import android.net.NetworkInfo import android.os.Build import androidx.annotation.RequiresApi import com.detectnetworkchange.connectivity.ConnectivityProviderImpl import com.detectnetworkchange.connectivity.ConnectivityProviderLegacyImpl interface ConnectivityProvider { fun subscribe() fun getNetworkState(): NetworkState @Suppress("MemberVisibilityCanBePrivate", "CanBeParameter") sealed class NetworkState { object NotConnectedState : NetworkState() sealed class ConnectedState(val hasInternet: Boolean) : NetworkState() { @RequiresApi(Build.VERSION_CODES.LOLLIPOP) data class Connected(val capabilities: NetworkCapabilities) : ConnectedState( capabilities.hasCapability(NET_CAPABILITY_INTERNET) ) @Suppress("DEPRECATION") data class ConnectedLegacy(val networkInfo: NetworkInfo) : ConnectedState( networkInfo.isConnectedOrConnecting ) } } companion object { @JvmStatic fun createProvider(context: Context): ConnectivityProvider { val cm = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { ConnectivityProviderImpl(cm) } else { ConnectivityProviderLegacyImpl(context, cm) } } } }
Extend ConnectivityProvider interface
Now create a abstract class named ConnectivityProviderBaseImpl which extends ConnectivityProvider interface, like below
package com.detectnetworkchange.connectivity.base import com.detectnetworkchange.CONNECTED import com.detectnetworkchange.DISCONNECTED import com.detectnetworkchange.NetWorkManger import com.detectnetworkchange.connectivity.base.ConnectivityProvider.NetworkState abstract class ConnectivityProviderBaseImpl : ConnectivityProvider { override fun subscribe() { subscribeListener() //init status dispatchChange(getNetworkState()) } protected fun dispatchChange(state: NetworkState) { val networkState = if (state.hasInternet()) CONNECTED else DISCONNECTED if (networkState != NetWorkManger.networkStatus.value) { NetWorkManger.networkStatus.postValue(networkState) } } private fun NetworkState.hasInternet(): Boolean { return (this as? NetworkState.ConnectedState)?.hasInternet == true } protected abstract fun subscribeListener() }
Write a actual implementation of ConnectivityProvider
package com.detectnetworkchange.connectivity import android.net.ConnectivityManager import android.net.ConnectivityManager.NetworkCallback import android.net.Network import android.net.NetworkCapabilities import android.os.Build import androidx.annotation.RequiresApi import com.detectnetworkchange.connectivity.base.ConnectivityProvider.NetworkState import com.detectnetworkchange.connectivity.base.ConnectivityProvider.NetworkState.ConnectedState.Connected import com.detectnetworkchange.connectivity.base.ConnectivityProvider.NetworkState.NotConnectedState import com.detectnetworkchange.connectivity.base.ConnectivityProviderBaseImpl @RequiresApi(Build.VERSION_CODES.N) class ConnectivityProviderImpl(private val cm: ConnectivityManager) : ConnectivityProviderBaseImpl() { private val networkCallback = ConnectivityCallback() override fun subscribeListener() { cm.registerDefaultNetworkCallback(networkCallback) } override fun getNetworkState(): NetworkState { val capabilities = cm.getNetworkCapabilities(cm.activeNetwork) return if (capabilities != null) { Connected(capabilities) } else { NotConnectedState } } private inner class ConnectivityCallback : NetworkCallback() { override fun onCapabilitiesChanged(network: Network, capabilities: NetworkCapabilities) { dispatchChange(Connected(capabilities)) } override fun onLost(network: Network) { dispatchChange(NotConnectedState) } } }
package com.detectnetworkchange.connectivity import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.net.ConnectivityManager import android.net.ConnectivityManager.CONNECTIVITY_ACTION import android.net.ConnectivityManager.EXTRA_NETWORK_INFO import android.net.NetworkInfo import com.detectnetworkchange.connectivity.base.ConnectivityProvider.NetworkState import com.detectnetworkchange.connectivity.base.ConnectivityProvider.NetworkState.ConnectedState.ConnectedLegacy import com.detectnetworkchange.connectivity.base.ConnectivityProvider.NetworkState.NotConnectedState import com.detectnetworkchange.connectivity.base.ConnectivityProviderBaseImpl @Suppress("DEPRECATION") class ConnectivityProviderLegacyImpl( private val context: Context, private val cm: ConnectivityManager ) : ConnectivityProviderBaseImpl() { private val receiver = ConnectivityReceiver() override fun subscribeListener() { context.registerReceiver(receiver, IntentFilter(CONNECTIVITY_ACTION)) } override fun getNetworkState(): NetworkState { val activeNetworkInfo = cm.activeNetworkInfo return if (activeNetworkInfo != null) { ConnectedLegacy(activeNetworkInfo) } else { NotConnectedState } } private inner class ConnectivityReceiver : BroadcastReceiver() { override fun onReceive(c: Context, intent: Intent) { // on some devices ConnectivityManager.getActiveNetworkInfo() does not provide the correct network state val networkInfo = cm.activeNetworkInfo val fallbackNetworkInfo: NetworkInfo? = intent.getParcelableExtra(EXTRA_NETWORK_INFO) // a set of dirty workarounds val state: NetworkState = if (networkInfo?.isConnectedOrConnecting == true) { ConnectedLegacy(networkInfo) } else if (networkInfo != null && fallbackNetworkInfo != null && networkInfo.isConnectedOrConnecting != fallbackNetworkInfo.isConnectedOrConnecting ) { ConnectedLegacy(fallbackNetworkInfo) } else { val state = networkInfo ?: fallbackNetworkInfo if (state != null) ConnectedLegacy(state) else NotConnectedState } dispatchChange(state) } } }
Let’s create a NetWorkManger class
In this class we have one live data object which hold the internet state, It can be accessible threw out the application.
package com.detectnetworkchange import androidx.lifecycle.MutableLiveData const val DISCONNECTED = 0 const val CONNECTED = 1 object NetWorkManger { val networkStatus = MutableLiveData<Int>() fun isDisconnected(): Boolean { return networkStatus.value == DISCONNECTED } } class NetWorkDisconnectedException : Throwable()
Finally subscribe the ConnectivityProvider instance in application class
package com.detectnetworkchange import android.app.ActivityManager import android.app.Application import android.content.Context import android.os.Build import android.os.Process import com.detectnetworkchange.connectivity.base.ConnectivityProvider class DetectNetworkChangeDemoApp : Application() { override fun onCreate() { super.onCreate() if (isMainProcess()) { ConnectivityProvider.createProvider(this).subscribe() } } // your package name is the same with your main process name private fun isMainProcess(): Boolean { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { packageName == getProcessName() } else packageName == getProcessNameLegacy() } // you can use this method to get current process name, you will get private fun getProcessNameLegacy(): String? { val mypid = Process.myPid() val manager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val infos = manager.runningAppProcesses for (info in infos) { if (info.pid == mypid) { return info.processName } } // may never return null return null } }
This way you can observe network changes
package com.detectnetworkchange import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Observer import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Suppose you want to check network status before calling APIs then use this way Log.d("MainActivity","Network connected "+!NetWorkManger.isDisconnected()) // if you want observe network status then use this way NetWorkManger.networkStatus.observe(this, Observer { when (it) { CONNECTED -> status.text ="Internet is connected" DISCONNECTED -> status.text ="Internet disconnected" } }) } }