Connectivity Manager is an Android system service that provides applications with information about the device’s network connection status. It allows checking internet availability, determining the network type (Wi-Fi, mobile data, Ethernet), tracking connection changes, and managing network requests based on connection quality. According to Android Developers, 2025, ConnectivityManager is the main API for network monitoring and has been part of the Android Framework since API Level 1.
Key Takeaways
ConnectivityManager is a system service of the Android operating system, accessible via Context.getSystemService(Context.CONNECTIVITY_SERVICE). It provides an API for obtaining information about the device’s network connection, monitoring network changes, and managing the application’s network requests. Connectivity Manager has been part of the Android Framework since the first platform version (API Level 1) and has undergone significant changes over the decades: from the simple getActiveNetworkInfo() to the modern reactive model with NetworkCallback and NetworkRequest.
The main capabilities of Connectivity Manager include: checking for an active network connection, determining the network type (Wi-Fi, mobile data, Ethernet, Bluetooth, VPN), real-time monitoring of network state changes, obtaining bandwidth and latency information, and managing the application’s network requests. ConnectivityManager is used in conjunction with WorkManager and Repository to implement Offline-First architecture, adaptive content loading, and application optimization based on connection quality.
Starting with Android 10 (API 29), Google changed the approach to working with ConnectivityManager. The getActiveNetworkInfo() method is declared deprecated, and instead it is recommended to use registerDefaultNetworkCallback() or registerNetworkCallback() with NetworkRequest. The new API provides more detailed network information, including the ability to detect captive portals (Wi-Fi with authentication) and assess connection quality. ConnectivityManager is also integrated with the Jetpack family: the ConnectivityManager library was released in 2024 as part of Jetpack to simplify network monitoring in Compose applications.
In modern Android architecture, Connectivity Manager is used at the repository or UseCase level to make decisions about network requests. The Repository Layer checks the network state before calling the API: if the network is unavailable, data is returned from the local storage (Room). If the network is available, a request to the server is made, and the result is saved in Room. The ViewModel subscribes to a Flow from Room and does not know about the details of network interaction — this allows each layer to be tested independently.
Connectivity Manager obtains network state information from the connectivity system service, which interacts with the Linux kernel’s network interfaces. When the device connects to Wi-Fi or turns on mobile data, the kernel notifies the system service, which updates its internal state and notifies all registered callbacks. The architecture of ConnectivityManager is built on the Observer pattern: the application registers a NetworkCallback and receives notifications about any network changes — connection establishment, connection loss, network type change, or quality degradation.
The modern ConnectivityManager API uses NetworkRequest to filter network events. NetworkRequest allows specifying requirements for the network: transport (Transport.WIFI, Transport.CELLULAR, Transport.ETHERNET), internet capability (NetworkCapabilities.NET_CAPABILITY_INTERNET), and other criteria. If an application only needs Wi-Fi for downloading large files, it creates a NetworkRequest with Transport.WIFI and registers a callback. The system will notify the application only when the Wi-Fi connection changes, ignoring mobile network events.
An important feature of Connectivity Manager on Android 12+ is capabilities-based networking. The application does not just check “is there internet,” but can assess what type of traffic is available. For example, NET_CAPABILITY_NOT_METERED indicates an unmetered connection (Wi-Fi), NET_CAPABILITY_NOT_ROAMING indicates the device is not roaming. This allows making decisions: download video only on Wi-Fi, postpone synchronization while roaming, or use mobile data only for critical requests.
| API Level | Recommended Method | Status |
|---|---|---|
| 1-22 | getActiveNetworkInfo() | Deprecated |
| 21+ | NetworkCallback + registerNetworkCallback() | Recommended |
| 24+ | registerDefaultNetworkCallback() | Recommended |
| 28+ | getActiveNetwork() + NetworkCapabilities | Alternative |
| 31+ | registerBestMatchingNetworkCallback() | New API |
Using Connectivity Manager in an Android application requires permissions. ACCESS_NETWORK_STATE is a mandatory permission for reading network information, declared in AndroidManifest.xml. Without this permission, ConnectivityManager will return null for getActiveNetwork() and will not invoke callbacks. For performing network operations, the INTERNET permission is also required. Starting with Android 10 (API 29), the application can check the network state without additional runtime permissions — ACCESS_NETWORK_STATE is a normal permission and is granted automatically upon installation.
The modern Connectivity Manager provides several key methods for working with the network. getActiveNetwork() (API 23+) returns the Network object of the current active network or null if the device is not connected. This method does not require callbacks and is suitable for one-time checks. The Network object can be passed to NetworkCapabilities to obtain detailed information: transport type, metered status, roaming, internet capability, and other characteristics.
registerDefaultNetworkCallback() (API 24+) is the preferred way to monitor the network. The application registers a callback that is invoked upon any changes to the default network (the network through which the application sends traffic). The callback receives a Network object that can be used for binding sockets and HTTP clients. This method replaces the deprecated getActiveNetworkInfo() and provides reactive network monitoring without polling.
registerNetworkCallback() (API 21+) allows subscribing to changes of a specific network type via NetworkRequest. For example, an application can track only Wi-Fi networks using new NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_WIFI).build(). The system will notify the application about Wi-Fi connection/disconnection without affecting mobile network events. NetworkCapabilities.getLinkDownstreamBandwidthKbps() returns an estimate of the downstream bandwidth in kbit/s, allowing content quality to be adapted to connection speed.
| Method | Minimum API | Purpose |
|---|---|---|
| getActiveNetwork() | 23 | Get the current active network |
| getNetworkCapabilities() | 21 | Get network capabilities (type, metered, roaming) |
| registerDefaultNetworkCallback() | 24 | Monitor the default network |
| registerNetworkCallback() | 21 | Monitor networks by NetworkRequest filter |
| unregisterNetworkCallback() | 21 | Unregister a callback |
| getActiveNetworkInfo() | 1 | Deprecated, do not use |
The Jetpack Connectivity library (androidx.core:core-ktx) provides convenient extensions for working with ConnectivityManager in Compose. The ConnectivityManager.observeAsState() function returns a State
ConnectivityManager.NetworkCallback is an abstract class with methods that are called by the system when the network state changes. onAvailable(Network) is called when a network becomes available. The application receives a Network object that can be used to bind sockets via Network.bindSocket(). onLost(Network) is called when a network becomes unavailable. The application should switch to local data or show a message about no connection. onCapabilitiesChanged(Network, NetworkCapabilities) is called when network characteristics change (for example, when switching from Wi-Fi to mobile data).
Proper handling of network changes requires considering the component lifecycle. The callback must be registered in onStart()/onResume() and unregistered in onStop()/onPause(). If the callback is not unregistered, it can continue running after the Activity is destroyed, causing memory leaks and potential NullPointerException when the callback tries to update the UI of a destroyed component. Use lifecycleScope or repeatOnLifecycle for automatic registration management. In Jetpack Compose, use DisposableEffect for callback registration and unregistration.
Captive portal handling is an important feature of ConnectivityManager starting from Android 10. A CAPTIVE_PORTAL is a scenario where a Wi-Fi network is available but requires authentication through a web page (airports, hotels, cafes). NetworkCapabilities.NET_CAPABILITY_VALIDATED indicates that the network has full internet access. If NET_CAPABILITY_VALIDATED is absent, the application can open a browser for captive portal authentication. The isCaptivePortal() method, added in Android 11 (API 30), is used to detect captive portals.
ConnectivityManager allows requesting a network for specific purposes through requestNetwork() and bindProcessToNetwork(). For example, an application for downloading large files can request a Wi-Fi network even if mobile data is active. To do this, a NetworkRequest is created with addTransportType(TRANSPORT_WIFI), and when Wi-Fi becomes available, the system calls onAvailable(). The application binds sockets to this network via network.bindSocket() or OkHttp with a configured Network object. This provides flexible control over the use of network interfaces.
Let’s look at a complete example of using ConnectivityManager with the modern API (NetworkCallback) in Clean Architecture. NetworkMonitor is a wrapper class around ConnectivityManager that provides reactive network status via StateFlow. The ViewModel subscribes to this Flow and passes the state to the UI. The Repository uses NetworkMonitor to make decisions about network requests. This approach ensures testability and isolation of platform dependencies.
The example below shows how to correctly use ConnectivityManager with registerDefaultNetworkCallback. The NetworkMonitor class encapsulates work with the system service and provides a clean Kotlin Flow
class NetworkMonitor(
private val connectivityManager: ConnectivityManager
) {
val isOnline: StateFlow<Boolean> = callbackFlow {
val callback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
trySend(true)
}
override fun onLost(network: Network) {
trySend(false)
}
override fun onCapabilitiesChanged(
network: Network,
caps: NetworkCapabilities
) {
val connected = caps.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET
)
trySend(connected)
}
}
connectivityManager.registerDefaultNetworkCallback(callback)
awaitClose {
connectivityManager.unregisterNetworkCallback(callback)
}
}.stateIn(
CoroutineScope(Dispatchers.Default),
SharingStarted.WhileSubscribed(5000),
initialValue = checkInitialState()
)
private fun checkInitialState(): Boolean {
val network = connectivityManager.getActiveNetwork() ?: return false
val caps = connectivityManager.getNetworkCapabilities(network) ?: return false
return caps.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET
)
}
}
The ViewModel subscribes to NetworkMonitor.isOnline via stateIn() and passes the state to Compose. The Repository checks the current isOnline.value before calling the API: if false — returns a Flow from Room. If true — calls the API, saves the result in Room, and returns a Flow from Room. WorkManager uses NetworkType.CONNECTED to constrain background tasks. Testing NetworkMonitor is done with a mock ConnectivityManager object and a fake NetworkCallback, allowing any network scenario to be emulated in unit tests.
The first rule of working with ConnectivityManager is not to use the deprecated API. getActiveNetworkInfo() has been deprecated since API 29 and may return incorrect data on newer Android versions. Instead, use getActiveNetwork() + getNetworkCapabilities() for one-time checks and registerDefaultNetworkCallback() for continuous monitoring. The old method also does not distinguish between networks with captive portals and full internet access, leading to false positives.
The second rule is to always unregister the callback. If an Activity registers a NetworkCallback in onStart() but does not unregister it in onStop(), the callback continues running after the Activity is destroyed. This causes memory leaks and potential NullPointerException when the callback tries to update the UI of a destroyed component. Use lifecycleScope or repeatOnLifecycle for automatic registration management. In Jetpack Compose, use DisposableEffect for callback registration and unregistration.
The third common mistake is checking only for network availability without considering its quality. A simple “is there internet” check is not sufficient for making decisions. The application should check NET_CAPABILITY_NOT_METERED for downloading large files, NET_CAPABILITY_NOT_ROAMING for background synchronization, and NET_CAPABILITY_VALIDATED to confirm internet access. Ignoring these flags leads to the application trying to download video while roaming or synchronizing data through a hotel’s captive portal.
The fourth rule is not to use ConnectivityManager to check the availability of a specific server. ConnectivityManager reports the network state on the device, but does not guarantee that the server is reachable. To check API availability, use an HTTP request with a short timeout or a Health Check. ConnectivityManager + HTTP ping is a reliable combination: first check for network availability, then perform a lightweight request to the server to confirm actual reachability.
For unit tests, use Robolectric with ShadowConnectivityManager, which allows emulating network states. For integration tests — Android Test Orchestrator with Airplane Mode toggling. In tests, verify scenarios: transitioning from online to offline, Wi-Fi appearing while mobile data is active, network loss during a request, captive portal, roaming. For mocking in unit tests, use a wrapper interface (e.g., NetworkMonitorInterface) that can be replaced with a mock object without platform dependencies.
Frequently Asked Questions
The modern way is to use registerDefaultNetworkCallback() with NET_CAPABILITY_INTERNET check in onCapabilitiesChanged(). For a one-time check: connectivityManager.getActiveNetwork()?.let { caps -> caps.hasCapability(NET_CAPABILITY_INTERNET) } ?: false. The deprecated getActiveNetworkInfo() method is not recommended from API 29+.
To read network information, the android.permission.ACCESS_NETWORK_STATE permission is required. This is a normal permission — it is granted automatically when the application is installed and does not require a runtime request. For performing network operations (HTTP requests), the INTERNET permission is also required.
registerDefaultNetworkCallback() monitors the default network — the one through which the application sends its main traffic. registerNetworkCallback(NetworkRequest) monitors networks matching a given filter (e.g., only Wi-Fi). The default callback is simpler and covers 90% of scenarios, while a custom request is for specific network type requirements.
Use NetworkCapabilities: caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) for Wi-Fi, hasTransport(TRANSPORT_CELLULAR) for mobile data. Do not use ConnectivityManager.getActiveNetworkInfo().getType() — this method is deprecated. NetworkCapabilities is available via connectivityManager.getNetworkCapabilities(network).
getActiveNetworkInfo() is deprecated due to inaccuracy: it does not distinguish between networks with captive portals and full internet access, and does not provide bandwidth or roaming information. Starting with Android 10, this method may return null or incorrect data for multi-network connections. The replacement is getActiveNetwork() + NetworkCapabilities.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also