Difference between registerDefaultNetworkCallback and registerNetworkCallback

registerNetworkCallback() was added in API level 21 (Android 5.0, Lollipop). It allows you to listen for changes in networks which satisfy a certain transport type (WiFi, cellular, Bluetooth, ...) and capability (SMS, NOT_METERED, ...).

registerDefaultNetworkCallback() was added in API level 24 (Android 7.0, Nougat) and uses your callback when any network change occurs, regardless of transport type and capability.


Example for registerNetworkCallback(). At least in my case I do not care about the filters and want my code to run for any network type. This can be achieved with an empty Builder object:

/* Automatically start a download once an internet connection is established */
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
// could filter using .addCapability(int) or .addTransportType(int) on Builder
val networkChangeFilter = NetworkRequest.Builder().build()
cm.registerNetworkCallback(networkChangeFilter, 
    object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) = downloadStuff()
    }
)

Above code is equivalent to this code with registerDefaultNetworkCallback():

val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
cm.registerDefaultNetworkCallback(
    object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) = downloadStuff()
    }
)

The confusingly named NetworkRequest is actually just a filter for transport type and capability.


The Default version is less code, but has a lower API level and thus supports fewer phones (74% vs 94%). Since I could not find a backwards-compatible version of this API call in ConnectivityManagerCompat I recommend using the first version if API levels 21-23 matter to you.


As far as I understood, the difference between registerDefaultNetworkCallback and registerNetworkCallback it's only based on customisation.
registerDefaultNetworkCallback works (surprisingly) as a default network listener, while registerNetworkCallback it's more configurable. For example:

    val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager

    val builder = NetworkRequest.Builder()
    builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)

    val networkRequest = builder.build()
    connectivityManager.registerNetworkCallback(networkRequest, 
    object : ConnectivityManager.NetworkCallback () {
        override fun onAvailable(network: Network?) {
            super.onAvailable(network)
            Log.i("Test", "Network Available")
        }

        override fun onLost(network: Network?) {
            super.onLost(network)
            Log.i("Test", "Connection lost")
        }
    })

Here onAvailable will be called only if the user connects to a cellular network (by connecting to WiFi it won't log anything). The same does onLost when disconnecting from cellular network.

If we do it like this:

    connectivityManager.registerDefaultNetworkCallback(object  : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network?) {
            super.onAvailable(network)
            Log.i("Test", "Default -> Network Available")
        }

        override fun onLost(network: Network?) {
            super.onLost(network)
            Log.i("Test", "Default -> Connection lost")
        }
    })

Both functions work as default callbacks when the user is connecting (or disconnecting) to/from a network (it can be either WiFi or cellular).

These are just some very basic examples. Of course NetworkRequest can have a lot of configurations by setting its capability or transportType. You can read more about these in the official documentation of NetworkRequest.