NetworkCallback is an abstract class in the Android SDK for monitoring network state changes via ConnectivityManager. According to Android Developers Documentation (2025), using NetworkCallback allows your app to promptly respond to connection, disconnection, or changes in connection characteristics. ConnectivityManager.NetworkCallback provides detailed information about network type, captive portals, and internet loss without constantly polling the system service.
Key Takeaways
NetworkCallback is an abstract class from the android.net package, part of the Android SDK. It is designed to receive notifications about network connection state changes through the ConnectivityManager system service.
Before NetworkCallback, developers used BroadcastReceivers to track network changes. This approach required constant manifest registration, worked with delays, and did not provide detailed information about connection characteristics. Android 5.0 (API 21) introduced NetworkCallback as a more flexible and performant alternative.
The callback works asynchronously: the app subscribes to events via ConnectivityManager, and the system calls callback methods when the network state changes. This eliminates the need for periodic polling of network status, saving battery and CPU resources.
ConnectivityManager manages all network interfaces on the device — Wi-Fi, mobile data, Ethernet, VPN. When any of these interfaces change, the system creates a Network object and passes it to the corresponding method of the registered callback. Each Network has a unique identifier that changes on reconnection.
The callback is not tied to a specific network type — it can track all available interfaces simultaneously. To filter connection types, use the NetworkRequest class, which specifies the required transport protocols (Wi-Fi, cellular data, Ethernet) and network capabilities.
NetworkCallback registration is done via the ConnectivityManager.registerNetworkCallback method. The first parameter is a NetworkRequest.Builder describing the network requirements, the second is a callback instance. The ACCESS_NETWORK_STATE permission is required in the manifest.
class NetworkMonitor(private val context: Context) {
private val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE)
as ConnectivityManager
private val callback =
object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
Log.d("Network", "Available: ${network}")
}
override fun onLost(network: Network) {
Log.d("Network", "Lost: ${network}")
}
}
fun register() {
connectivityManager.registerNetworkCallback(
NetworkRequest.Builder().build(), callback
)
}
fun unregister() {
connectivityManager.unregisterNetworkCallback(callback)
}
}
It is recommended to register NetworkCallback when the app is in the foreground and cancel it when going to the background. In Activity, use onStart and onStop to manage the callback lifecycle. In Fragment, use onResume and onPause.
To simplify registration management, you can use Lifecycle-aware components. The AndroidX Lifecycle library allows you to create a custom LifecycleObserver that automatically registers and cancels the callback when the lifecycle state changes.
For background tasks, registration is done in a Service or WorkManager. Note that on Android 8+, background services have launch restrictions. WorkManager with NetworkType is a more reliable way to execute tasks under a specific network state, as it integrates with the compatibility API and respects Doze mode.
NetworkCallback provides a set of methods that are called when the network state changes. Not all methods need to be overridden — implement only those required for your app's specific task. onAvailable and onLost are the minimum required for basic connection monitoring.
| Method | When Called | Parameters |
|---|---|---|
| onAvailable | Network is available for use | Network — network object |
| onLost | Network is lost or disconnected | Network — network object |
| onCapabilitiesChanged | Network capabilities changed | Network, NetworkCapabilities |
| onBlockedStatusChanged | Blocking status changed | Network, Boolean |
| onNetworkSuspended | Network suspended by system | Network |
| onNetworkResumed | Network resumed after suspension | Network |
This method is key to obtaining detailed network information. The NetworkCapabilities parameter contains flags: NET_CAPABILITY_INTERNET — internet access available, NET_CAPABILITY_NOT_METERED — unmetered connection, NET_CAPABILITY_NOT_ROAMING — no roaming. You can also check signal latency and bandwidth.
Captive portals are a special case: when connecting to a public Wi-Fi network through a portal, the onCapabilitiesChanged method does not immediately show INTERNET. The network is available initially but without internet — browser authorization is required. Developers need to account for this delay in app logic.
Called when the system blocks network traffic for the app — for example, when data saver mode is enabled or background data is restricted. onBlockedStatusChanged lets the app know that its network requests are temporarily prohibited and switch to local processing.
Let's look at a practical NetworkCallback implementation for monitoring internet access and handling captive portals. The example below shows checking NET_CAPABILITY_INTERNET and validating the connection via an HTTP request to Google's server.
val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onCapabilitiesChanged(
network: Network,
caps: NetworkCapabilities
) {
val hasInternet = caps.hasCapability(
NetworkCapabilities.NET_CAPABILITY_INTERNET
)
val isMetered = caps.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_METERED
).not()
when {
hasInternet && isMetered ->
Log.d("Network", "Mobile data connected")
hasInternet ->
Log.d("Network", "Wi-Fi connected")
else ->
Log.d("Network", "No internet access")
}
}
override fun onLost(network: Network) {
Log.d("Network", "Connection lost: ${network}")
// Stop network requests
}
}
When connecting to a public network with authorization (cafe, airport), the system first reports onAvailable, but onCapabilitiesChanged may not show INTERNET. In such cases, additional verification is required via an HTTP request to a stable endpoint, such as https://www.google.com/generate_204.
If the request returns code 204 — internet is available. If a redirect (301, 302, 307) — browser authorization is required. In this case, you can open a WebView or Intent with the redirect URL to complete portal authentication.
fun Context.validateInternet(network: Network) {
CoroutineScope(Dispatchers.IO).launch {
try {
val url = URL("https://www.google.com/generate_204")
val connection =
network.openConnection(url) as HttpURLConnection
connection.instanceFollowRedirects = false
connection.connect()
when (connection.responseCode) {
HttpURLConnection.HTTP_NO_CONTENT ->
Log.d("Network", "Internet is available")
in HttpURLConnection.HTTP_MOVED_PERM
..HttpURLConnection.HTTP_TEMP_REDIRECT ->
Log.d("Network", "Captive portal detected")
}
connection.disconnect()
} catch (e: Exception) {
Log.e("Network", "Validation failed: ${e.message}")
}
}
}
Before NetworkCallback, the primary method for network monitoring was BroadcastReceiver with the android.net.conn.CONNECTIVITY_CHANGE filter. This approach had significant drawbacks: several-second delays, no interface type information, and increased power consumption due to constant device wake-ups.
A modern alternative is LiveData or StateFlow combined with NetworkCallback. The pattern involves wrapping the callback in a reactive stream that automatically notifies the UI about state changes. For example, a MutableStateFlow with NetworkStatus type updates inside callback methods, and a ViewCollector subscribes to the changes.
| Method | API Level | Latency | Detail Level | Power Consumption |
|---|---|---|---|---|
| BroadcastReceiver | 1+ | high | low | high |
| NetworkCallback | 21+ | low | high | low |
| ConnectivityManager.getActiveNetwork | 23+ | instant | medium | none |
| NWPathMonitor (iOS) | iOS 12+ | low | high | low |
Starting from Android 10, background restrictions are stricter, and NetworkCallback may not be called when the app is in the background. For critical tasks — such as data loading when network becomes available — use WorkManager with NetworkType.CONNECTED constraint. WorkManager guarantees task execution when network conditions are met.
In Android 12+, there is a restriction on manifest registration of BroadcastReceiver for CONNECTIVITY_ACTION. Developers must migrate to NetworkCallback or use WorkManager. Google Play policy since August 2022 requires removal of manifest registration for this action.
Frequently Asked Questions
BroadcastReceiver with CONNECTIVITY_CHANGE only provides the fact of network change without details and with a delay of up to several seconds. NetworkCallback works asynchronously, provides a Network object, interface type, connection capabilities, and does not require manifest registration, which is prohibited on Android 12+.
On Android 10+, background restrictions may delay or prevent NetworkCallback from being called. For background tasks, use WorkManager with NetworkType constraint — it guarantees task execution when conditions are met regardless of power saving mode.
Call the unregisterNetworkCallback method on ConnectivityManager, passing the same callback instance used during registration. An unregistered callback may cause a memory leak because the system holds a reference to it. Always unregister in onStop or onDestroy.
NetworkCallback is available starting from API Level 21 (Android 5.0 Lollipop). For devices with older versions, use BroadcastReceiver or compatibility libraries such as AndroidX Activity NetworkCallback, which wrap the API for broader support.
Use ConnectivityManager.getActiveNetwork (API 23+) together with getNetworkCapabilities. The method returns the current active network synchronously, without subscribing to changes. For API 21-22, use getActiveNetworkInfo, which is marked as deprecated in newer versions.
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