Cerberos
Cerberos

Reputation: 101

What's the "appropriate" way to listen to network state changes indefinitely on Android?

I'm working on an Android application which monitors the device's network usage in the background. As far as I know, a couple years ago the go-to approach would have been to register a BroadcastReceiver which catches every CONNECTIVITY_CHANGE event, but it seems like it was deprecated in Android 7. I can see a class named JobScheduler has been introduced since as a sort of replacement, but I'm not sure that might suit this specific use case.

Upvotes: 0

Views: 617

Answers (1)

Abu Yousuf
Abu Yousuf

Reputation: 6107

Use ConnectivityManager class to listen about connectivity change.

From official doc

Class that answers queries about the state of network connectivity. It also notifies applications when network connectivity changes.

Use registerNetworkCallback to receive notifications about all networks which satisfy the given NetworkRequest

Here is sample code in Kotlin:

enum class NetworkResult {
    CONNECTED,
    DISCONNECTED,
    DISCONNECTING
}


class NetworkCallback : ConnectivityManager.NetworkCallback(){

    val result = MutableLiveData<NetworkResult>()

    override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
        super.onCapabilitiesChanged(network, networkCapabilities)
    }

    override fun onLost(network: Network) {
        Timber.i("onLost networkL $network")
        result.postValue(NetworkResult.DISCONNECTED)
    }

    override fun onLosing(network: Network, maxMsToLive: Int) {
        Timber.i("onLosing: network: $network maxMsToLive: $maxMsToLive")
        result.postValue(NetworkResult.DISCONNECTING)
    }

    override fun onAvailable(network: Network) {
        Timber.i("onAvailable: network: $network")
        result.postValue(NetworkResult.CONNECTED)
    }
}


class ConnectivityFactory {

   fun internetRequest() : NetworkRequest{
     return NetworkRequest.Builder()
            .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
            .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
            .build()
  }
}


class NetworkConnectionManager(val context: Context){

    private val factory : ConnectivityFactory = ConnectivityFactory()
    private val callback : NetworkCallback = NetworkCallback()

    private val connectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager

    val result : LiveData<NetworkResult>  get() = callback.result

    fun registerCallback(){
        val request = factory.internetRequest()
        connectivityManager.registerNetworkCallback(request, callback)
    }

    fun unregisterCallback(){
        connectivityManager.unregisterNetworkCallback(callback)
    }

}

Usage:

val networkManager : NetworkConnectionManager by lazy { NetworkConnectionManager(this)  } 

// observer state 
networkManager.result.observe(this, Observer {
    Timber.i(it.name)
})


// register 
networkManager.registerCallback()()
// unregister 
networkManager.unregisterCallback()

Upvotes: 2

Related Questions