Android ConnectivityManager callbacks not working

492 Views Asked by At

I need to check the current internet availability. Since many of the old calls are deprecated I use the

ConnectivityManager.NetworkCallback() 

approach with a callback. However, when implementing something like this:

private val connectivityCallback = object : ConnectivityManager.NetworkCallback() {
      override fun onAvailable(network: Network) {
            Log.debug("Available $network")
      }

      override fun onLost(network: Network) {
            Log.debug("Lost $network")
      }
}

the onAvailable is not working reliable.

This causes issues when working with WIFI and Cellular networks at the same time. When the users are deactivating wifi I get the callback for the lost network of the wifi. But I don not get an Available call for the cellular network. Thus my app is believing I have no internet.

What am I doing wrong?

2

There are 2 best solutions below

0
devNight On
fun register() {
    //Internet control with NetworkCallback on Android 9 and higher versions
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
        val connectivityManager =
            mContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        //Checking the internet absence status when the application is first opened
        if (connectivityManager.activeNetwork == null) {
            result(false, null)
        }

        //OnLost method works when there is internet, then when internet is turned off            networkCallback = object : ConnectivityManager.NetworkCallback() {
            override fun onLost(network: Network) {
                super.onLost(network)
                result(false, null)
            }

            //Detection of whether the network where the internet comes from is Wifi or mobile location (Cellular)
            override fun onCapabilitiesChanged(
                network: Network,
                networkCapabilities: NetworkCapabilities
            ) {
                super.onCapabilitiesChanged(network, networkCapabilities)
                when {
                    networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
                        // WIFI
                        result(true, ConnectionType.Wifi)
                    }

                    else -> {
                        // CELLULAR
                        result(true, ConnectionType.Cellular)
                    }
                }
            }
        }
        connectivityManager.registerDefaultNetworkCallback(networkCallback)
    } else {
        //Internet control with Intent Filter on Android 8 and below
        val intentFilter = IntentFilter()
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE")
        mContext.registerReceiver(networkChangeReceiver, intentFilter)
    }
}

I found a result like this, maybe it will help you

0
Mai3 On

Since the function used to register ConnectivityManager.NetworkCallback() isn't provided, I'm assuming, based on callbacks got,

registerNetworkCallback (NetworkRequest request, 
                ConnectivityManager.NetworkCallback networkCallback)

is used to register the callback.

https://developer.android.com/reference/android/net/NetworkRequest

In the starting paragraphs, difference between registerNetworkCallback and requestNetwork is stated,

For NetworkRequest,

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

registerNetworkCallback will receive callbacks for all the networks matching.

onAvailable is called twice if both are connected. When wifi is lost, onLost is called only for wifi and technically mobile data hasn't been lost, onAvailable is not called again.

requestNetwork will receive callback for the best possible network and system keeps up with the use case.

When both are connected, onAvailable is called for wifi, as system determines it is better. When wifi is lost, onLost is called, and now best possible network is mobile data, so onAvailable is called for mobile data.

Either requestNetwork or registerDefaultNetworkCallback can be used for the use case mentioned in the question.