I open-sourced a minimal Kotlin Multiplatform connectivity monitor that exposes a single
StateFlow<ConnectivityStatus>
from shared code.
Android: ConnectivityManager
callbacks • iOS: SCNetworkReachability
(no CocoaPods).
- Repo: https://github.com/Qandil11/KMP-Connectivity-Monitor
- Demo (YouTube): https://www.youtube.com/watch?v=ItkwVbaN8eo
Why I built this
Most apps need to react to connectivity. I wanted a production-style, zero-friction approach for Compose Multiplatform that keeps:
- one API in
commonMain
- native implementations per platform
- no CocoaPods requirement on iOS
- easy to use from Compose
So I built KMP Connectivity Monitor.
The tiny API (commonMain)
// com.qandil.kmpconnectivity.connectivity.Connectivity.kt
package com.qandil.kmpconnectivity.connectivity
import kotlinx.coroutines.flow.StateFlow
enum class ConnectivityStatus { Online, Offline, Unavailable }
interface ConnectivityMonitor {
val status: StateFlow<ConnectivityStatus>
fun start()
fun stop()
}
expect class ConnectivityMonitorFactory {
fun create(): ConnectivityMonitor
}
Android actual — ConnectivityManager
Listen to ConnectivityManager callbacks and update a MutableStateFlow.
// shared/src/androidMain/.../connectivity/Connectivity.android.kt (excerpt)
private fun updateNow() {
val caps = cm.getNetworkCapabilities(cm.activeNetwork)
val online = caps?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) == true &&
caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
scope.launch {
_status.value = if (online) ConnectivityStatus.Online else ConnectivityStatus.Offline
}
}
override fun start() {
updateNow()
val req = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()
cm.registerNetworkCallback(req, callback)
}
Android manifest (app module):
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Tip (for library lint): shared/src/androidMain/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
iOS actual — SystemConfiguration (no Pods)
Use SCNetworkReachability to monitor the default route and update the flow.
// shared/src/iosMain/.../connectivity/Connectivity.ios.kt (excerpt)
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
private fun update(flags: SCNetworkReachabilityFlags) {
val reachable = flags.toInt() and kSCNetworkReachabilityFlagsReachable.toInt() != 0
val needsConn = flags.toInt() and kSCNetworkReachabilityFlagsConnectionRequired.toInt() != 0
val online = reachable && !needsConn
scope.launch {
_status.value = if (online) ConnectivityStatus.Online else ConnectivityStatus.Offline
}
}
Gradle link (SystemConfiguration):
// shared/build.gradle.kts
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
kotlin {
targets.withType<KotlinNativeTarget>().configureEach {
binaries.all { linkerOpts("-framework", "SystemConfiguration") }
}
}
Prefer NWPathMonitor? Switch the iOS impl to Network.framework and link that instead.
Using it in Compose
@Composable
fun Main(factory: ConnectivityMonitorFactory) {
val monitor = remember(factory) { factory.create() }
val status by monitor.status.collectAsState(ConnectivityStatus.Unavailable)
LaunchedEffect(Unit) { monitor.start() }
DisposableEffect(Unit) { onDispose { monitor.stop() } }
// render your UI (e.g., a status card with Online / Offline / … Checking)
}
Platform entry points:
// Android
setContent { Main(factory = com.qandil.kmpconnectivity.connectivity.ConnectivityMonitorFactory(this)) }
// iOS
Main(factory = com.qandil.kmpconnectivity.connectivity.ConnectivityMonitorFactory())
How to run
Android: ./gradlew :androidApp:assembleDebug (or Run from Android Studio)
iOS: Run from Android Studio’s iOS config or your Xcode project (Simulator/Device)
Roadmap / help wanted
Flow.retryWhenOnline(monitor) helper
Expose network type (Wi-Fi/Cellular)
Tests with stubs
If this was useful, a ⭐ or PR would mean a lot:
Repo: https://github.com/Qandil11/KMP-Connectivity-Monitor
License
MIT (in the repo).
Top comments (0)