Monitor connectivity status and connection metering

The ConnectivityManager provides an API to request the device connect to a network based on different capabilities and transport options. A callback implementation provides information to your app regarding the connection state as well as the capabilities of the currently connected network. Using this API allows you to determine if the device is currently connected to a network that satisfies your app’s requirements.

Check meteredness

The NET_CAPABILITY_TEMPORARILY_NOT_METERED capability was added in Android 11 (API level 30), and tells you if the network you're using is unmetered based on information provided by cellular carriers. This state changes as the device moves in and out of meteredness, so your app must take action to interrupt transfers when this capability is removed from a network to avoid unexpected charges. Apps that cannot respond dynamically should use only NET_CAPABILITY_NOT_METERED.

NET_CAPABILITY_TEMPORARILY_NOT_METERED is used alongside NET_CAPABILITY_NOT_METERED. The existing flag indicates if a network is always unmetered, and applies to both Wi-Fi and cellular connections.

The difference between the two flags is that NET_CAPABILITY_TEMPORARILY_NOT_METERED may change without the network type changing. Apps that target Android 11 and higher can use the NET_CAPABILITY_TEMPORARILY_NOT_METERED flag. On devices running on Android 9 (API level 28) and lower, the OS will not report on the flag. For apps running on Android 10 (API level 29), this flag may be available, depending on the device it is running on.

Configure a network request

Declare a NetworkRequest that describes your app’s needs for a network connection. This request allows you to specify the transport type of the network, such as Wi-Fi or cellular connection, as well as the capabilities that the network has, such as connection to the internet. The following code creates a request for a network that is connected to the internet and uses either Wi-Fi or cellular for the transport type:

Kotlin

val networkRequest = NetworkRequest.Builder()
        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
        .build()

Java

NetworkRequest networkRequest = new NetworkRequest.Builder()
        .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
        .build();

Mobile data costs tend to be significantly higher than Wi-Fi and Ethernet costs. When on a metered connection, your app should try to reduce data consumption, or even delay it until it is on a non-metered connection.

Configure a network callback

Registering the NetworkRequest with the ConnectivityManager requires a NetworkCallback implementation to receive notifications about the connection state and capability changes.

The following are common functions to implement in the NetworkCallback:

  • onAvailable() indicates that the device is connected to a new network or that this network otherwise became available. This network must satisfy the capabilities and transport type requirements specified in the NetworkRequest.
  • onLost() indicates that the network is no longer available.
  • onCapabilitiesChanged() indicates that the capabilities of the network have changed. The NetworkCapabilities object provides information about the current capabilities of the network.

Kotlin

private val networkCallback = object : ConnectivityManager.NetworkCallback() {
    // network is available for use
    override fun onAvailable(network: Network) {
        super.onAvailable(network)
    }

    // Network capabilities have changed for the network
    override fun onCapabilitiesChanged(
            network: Network,
            networkCapabilities: NetworkCapabilities
    ) {
        super.onCapabilitiesChanged(network, networkCapabilities)
        val hasCellular = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
        val hasWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
    }

    // lost network connection
    override fun onLost(network: Network) {
        super.onLost(network)
    }
}

Java

private ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(@NonNull Network network) {
        super.onAvailable(network);
    }

    @Override
    public void onLost(@NonNull Network network) {
        super.onLost(network);
    }

    @Override
    public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
        super.onCapabilitiesChanged(network, networkCapabilities);
        boolean hasCellular = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
        boolean hasWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
    }
};

Register for network updates

Once the NetworkRequest and NetworkCallback are declared, add a registerNetworkCallback() to be alerted when the system finds a network matching the required capabilities.

Kotlin

val connectivityManager = getSystemService(ConnectivityManager::class.java)
connectivityManager.requestNetwork(networkRequest, networkCallback)

Java

ConnectivityManager connectivityManager =
        getSystemService(ConnectivityManager::class.java);
connectivityManager.requestNetwork(networkRequest, networkCallback);