Cesar
Cesar

Reputation: 2057

Possible to observe network status?

I'm wondering if there's a way to somehow register as an observer for network access (and have some callback function run when the internet is avaliable), or if polling is the only way. Thanks!

Upvotes: 1

Views: 2906

Answers (2)

Bogdan Khrystov
Bogdan Khrystov

Reputation: 81

My solution for observing network state, also wifi/cellular data connection can be observed independently:

    import android.annotation.SuppressLint
    import android.content.Context
    import android.net.ConnectivityManager
    import android.net.Network
    import android.net.NetworkCapabilities
    import android.net.NetworkRequest
    import kotlinx.coroutines.CoroutineScope
    import kotlinx.coroutines.Dispatchers
    import kotlinx.coroutines.SupervisorJob
    import kotlinx.coroutines.flow.MutableStateFlow
    import kotlinx.coroutines.flow.SharingStarted
    import kotlinx.coroutines.flow.asStateFlow
    import kotlinx.coroutines.flow.combine
    import kotlinx.coroutines.flow.stateIn
    
object InternetConnectionObserver {
    
        private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
    
        private val _connectionStateWifi = MutableStateFlow(NetworkState.UNDEFINED)
        val connectionStateWifi = _connectionStateWifi.asStateFlow()
    
        private val _connectionStateCellular = MutableStateFlow(NetworkState.UNDEFINED)
        val connectionStateCellular = _connectionStateCellular.asStateFlow()
    
        val connectionState =
            _connectionStateWifi.combine(_connectionStateCellular) { wifiState, cellularState ->
                if (wifiState == NetworkState.CONNECTED || cellularState == NetworkState.CONNECTED) {
                    NetworkState.CONNECTED
                } else {
                    NetworkState.NOT_CONNECTED
                }
            }.stateIn(scope, SharingStarted.Eagerly, NetworkState.UNDEFINED)
    
        @SuppressLint("MissingPermission")
        fun start(context: Context) {
            val connectivityManager =
                context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
            connectivityManager?.let {
                val wifiNetworkCallback = object : ConnectivityManager.NetworkCallback() {
                    override fun onAvailable(network: Network) {
                        super.onAvailable(network)
                        _connectionStateWifi.value = NetworkState.CONNECTED
                    }
    
                    override fun onLost(network: Network) {
                        super.onLost(network)
                        _connectionStateWifi.value = NetworkState.NOT_CONNECTED
                    }
                }
                val cellularNetworkCallback = object : ConnectivityManager.NetworkCallback() {
                    override fun onAvailable(network: Network) {
                        super.onAvailable(network)
                        _connectionStateCellular.value = NetworkState.CONNECTED
                    }
    
                    override fun onLost(network: Network) {
                        super.onLost(network)
                        _connectionStateCellular.value = NetworkState.NOT_CONNECTED
                    }
                }
                val wifiRequest = NetworkRequest.Builder()
                    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                    .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
                    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                    .build()
                val cellularRequest = NetworkRequest.Builder()
                    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                    .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                    .build()
                connectivityManager.registerNetworkCallback(wifiRequest, wifiNetworkCallback)
                connectivityManager.registerNetworkCallback(cellularRequest, cellularNetworkCallback)
            }
        }
    
        fun isConnected(): Boolean = connectionState.value == NetworkState.CONNECTED
    
        fun isWifiConnected() = connectionStateWifi.value == NetworkState.CONNECTED
    
        fun isCellularConnected() = connectionStateCellular.value == NetworkState.CONNECTED
    
        enum class NetworkState {
            CONNECTED, NOT_CONNECTED, UNDEFINED
        }
    }

Upvotes: 0

kovalevfm
kovalevfm

Reputation: 124

You can register receiver:

//Callback  
private final BroadcastReceiver mNetworkStateReceiver = new BroadcastReceiver() {
    @Override
        public void onReceive(Context context, Intent intent) {
           //network state changes, you can process it, inforamtion in intent
        }
    };

//registering recievr in actibity or in service
IntentFilter mNetworkStateFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(mNetworkStateReceiver , mNetworkStateFilter);

Detail at: http://developer.android.com/reference/android/net/ConnectivityManager.html

Upvotes: 5

Related Questions