Reputation: 2057
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
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
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