I want to get Network State means whether the Connected network has internet connection in Jetpack Compose. How to achieve it
-
3Jetpack Compose generally focuses on UI concerns. Determining the state of the network is not directly related to the UI. – CommonsWare Jul 19 '21 at 17:26
-
I think @CommonsWare makes the most sense on this question. The UI shouldn't be directly tied to something like that. Would make most sense to extract that to the VM layer, and pass in a state / boolean into the composable itself. – Jüri Kiin Jul 07 '22 at 19:04
3 Answers
If your running into trouble with the connectivityManager.activeNetworkInfo
being deprecated, try using this:
private fun isInternetAvailable(context: Context): Boolean {
var result = false
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
val networkCapabilities = connectivityManager.activeNetwork ?: return false
val actNw = connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
result = when {
actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
else -> false
}
} else {
connectivityManager.run {
connectivityManager.activeNetworkInfo?.run {
result = when (type) {
ConnectivityManager.TYPE_WIFI -> true
ConnectivityManager.TYPE_MOBILE -> true
ConnectivityManager.TYPE_ETHERNET -> true
else -> false
}
}
}
}
return result
}
I got the answer from the accepted answer of another question. Feel free to check it out: activeNetworkInfo is Deprecated
When working with JC, use this to access the context:
val context = LocalContext.current

- 567
- 6
- 16
-
This should be the accepted answer. As James has pointed out, using activeNetworkInfo is deprecated. – Tom Taila Feb 25 '22 at 20:04
val connectivityManager
= getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val activeNetworkInfo = connectivityManager.getActiveNetworkInfo()
Text(
if(
activeNetworkInfo != null && activeNetworkInfo.isConnected()
) "Connected"
else "Disconnected"
)
This is a Composable which displays the state of the network. As correctly pointed out in the comment above, JC is focused more on the UI, so all the rest of the stuff is still the same old Android way. JC just efficiensizes(?) the GUI development

- 5,477
- 2
- 11
- 42
-
This only show about connected Wi-Fi or Cellular network but not about the active Internet connection – Jul 20 '21 at 15:45
-
-
-
1
-
Actually I don't have access to My Android Studio for some days so I'm trying to clear all error or stops that's why was asking? – Jul 20 '21 at 15:56
-
Confirmed from the docs as well. It tells internet connection not connection type. It is the only way to know it, that is mentioned in the docs. – Richard Onslow Roper Jul 20 '21 at 15:56
-
-
1
I'm sharing my connectivity flow solution here, even though an answer has been accepted. This solution seamlessly integrates with Jetpack Compose and has been thoroughly debugged and simplified. Feel free to try and copy-paste the solution.
It combines the solution used by Google in WorkManager and callbackFlow
.
Here are the relevant classes: NetworkState
, which holds the current network states, and ConnectionState
, which is important for UI components.
private data class NetworkState(
/** Determines if the network is connected. */
val isConnected: Boolean,
/** Determines if the network is validated - has a working Internet connection. */
val isValidated: Boolean,
/** Determines if the network is metered. */
val isMetered: Boolean,
/** Determines if the network is not roaming. */
val isNotRoaming: Boolean
)
sealed class ConnectionState {
object Available : ConnectionState()
object Unavailable : ConnectionState()
}
To compute the NetworkState
, use the activeNetworkState
property extension on ConnectivityManager
.
@Suppress("DEPRECATION")
private val ConnectivityManager.activeNetworkState: NetworkState
@SuppressLint("MissingPermission")
get() {
// Use getActiveNetworkInfo() instead of getNetworkInfo(network) because it can detect VPNs.
val info = activeNetworkInfo
val isConnected = info != null && info.isConnected
val isValidated = isActiveNetworkValidated
val isMetered = ConnectivityManagerCompat.isActiveNetworkMetered(this)
val isNotRoaming = info != null && !info.isRoaming
return NetworkState(isConnected, isValidated, isMetered, isNotRoaming)
}
For checking if the active network is validated, use the isActiveNetworkValidated
property extension on ConnectivityManager
.
private val ConnectivityManager.isActiveNetworkValidated: Boolean
@SuppressLint("RestrictedApi", "MissingPermission")
get() =
if (Build.VERSION.SDK_INT < 23) {
false // NET_CAPABILITY_VALIDATED not available until API 23. Used on API 26+.
} else
try {
val network = activeNetwork
val capabilities = getNetworkCapabilities(network)
(capabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) ?: false
} catch (exception: SecurityException) {
Timber.tag("NetworkStateTracker").e(exception, "Unable to validate active network")
false
}
A callbackFlow
to convert a NetworkCallback
to a Flow
. Everytime there is a callback method called, this function computes the ConnectivityState
and sends it.
/** Network Utility to observe Internet connectivity status */
@SuppressLint("MissingPermission")
@ExperimentalCoroutinesApi
private fun Context.observeConnectivityAsFlow() =
callbackFlow {
val connectivityManager =
getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
fun sendConnectionState() =
with(connectivityManager.activeNetworkState) {
if (Build.VERSION.SDK_INT < 23) {
if (isConnected) {
trySend(ConnectionState.Available)
} else {
trySend(ConnectionState.Unavailable)
}
} else {
if (isConnected && isValidated) {
trySend(ConnectionState.Available)
} else {
trySend(ConnectionState.Unavailable)
}
}
}
val networkRequest =
NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.build()
val networkCallback =
object : ConnectivityManager.NetworkCallback() {
// satisfies network capability and transport requirements requested in networkRequest
override fun onCapabilitiesChanged(
network: Network,
networkCapabilities: NetworkCapabilities
) {
sendConnectionState()
}
override fun onLost(network: Network) {
sendConnectionState()
}
}
connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
awaitClose {
connectivityManager.unregisterNetworkCallback(networkCallback)
}
}
.distinctUntilChanged()
.flowOn(Dispatchers.IO)
A publicly available method to collect the ConnectionState
@ExperimentalCoroutinesApi
@Composable
fun connectivityState(): State<ConnectionState> {
val context = LocalContext.current
return produceState<ConnectionState>(initialValue = ConnectionState.Unavailable) {
context.observeConnectivityAsFlow().collect { value = it }
}
}
And finally in your composable
@Composable
fun YourAwesomeComposable(
modifier: Modifier = Modifier,
) {
val networkConnectivity by connectivityState()
...
...
if (networkConnectivity == ConnectionState.Unavailable) {
// Unavailable UI
} else {
// Available UI
}
}

- 6,920
- 7
- 44
- 87