-
-
Save iRYO400/5da269f4d5edbc365c952bdcbdfe6b68 to your computer and use it in GitHub Desktop.
| import android.content.Context | |
| import android.content.Context.CONNECTIVITY_SERVICE | |
| import android.net.ConnectivityManager | |
| import android.net.Network | |
| import android.net.NetworkCapabilities | |
| import android.net.NetworkRequest | |
| import androidx.lifecycle.Lifecycle | |
| import androidx.lifecycle.LifecycleObserver | |
| import androidx.lifecycle.LifecycleOwner | |
| import androidx.lifecycle.OnLifecycleEvent | |
| import timber.log.Timber | |
| class ConnectivityMonitor( | |
| context: Context, | |
| lifecycleOwner: LifecycleOwner, | |
| private val callback: (Boolean) -> Unit | |
| ) : LifecycleObserver { | |
| private var connectivityManager = | |
| context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager | |
| private val networkRequest = NetworkRequest.Builder() | |
| .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) | |
| .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) | |
| .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) | |
| .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) | |
| .addTransportType(NetworkCapabilities.TRANSPORT_VPN) | |
| .build() | |
| init { | |
| lifecycleOwner.lifecycle.addObserver(this) | |
| } | |
| @Suppress("unused") | |
| @OnLifecycleEvent(Lifecycle.Event.ON_START) | |
| fun onResume() { | |
| toggleConnectionState(connectivityManager.isDefaultNetworkActive) | |
| connectivityManager.registerNetworkCallback(networkRequest, networkCallback) | |
| } | |
| @Suppress("unused") | |
| @OnLifecycleEvent(Lifecycle.Event.ON_STOP) | |
| fun onPause() { | |
| connectivityManager.unregisterNetworkCallback(networkCallback) | |
| } | |
| private fun toggleConnectionState(isConnected: Boolean) = callback.invoke(isConnected) | |
| private val networkCallback = object : ConnectivityManager.NetworkCallback() { | |
| override fun onCapabilitiesChanged( | |
| network: Network, | |
| networkCapabilities: NetworkCapabilities | |
| ) { | |
| super.onCapabilitiesChanged(network, networkCapabilities) | |
| Timber.d("onCapabilitiesChanged") | |
| lastInternetConnectionCheck() | |
| } | |
| override fun onAvailable(network: Network) { | |
| super.onAvailable(network) | |
| Timber.d("onAvailable") | |
| lastInternetConnectionCheck() | |
| } | |
| override fun onLost(network: Network) { | |
| super.onLost(network) | |
| Timber.d("onLost") | |
| lastInternetConnectionCheck() | |
| } | |
| private fun lastInternetConnectionCheck() = | |
| connectivityManager.allNetworks.forEach { network -> | |
| network?.let { | |
| connectivityManager.getNetworkCapabilities(it) | |
| ?.let { networkCapabilities -> | |
| val netInternet = | |
| networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) | |
| val transportCellular = | |
| networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) | |
| val transportWifi = | |
| networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) | |
| val transportEthernet = | |
| networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) | |
| val transportVpn = | |
| networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN) | |
| val isConnected = netInternet || | |
| transportWifi || transportCellular || | |
| transportEthernet || transportVpn | |
| Timber.d("Connections State $isConnected netInternet: $netInternet, WiFi: $transportWifi, Cellular: $transportCellular, Ethernet: $transportEthernet, VPN: $transportVpn") | |
| toggleConnectionState(isConnected) | |
| } | |
| } | |
| } | |
| } | |
| } |
Great! Thanks for this...
Can you please provide java code for the same ?
@igoswamirohit nope, I won't, you better try it yourself :)
Hi. Try to turn off all except cellular. And then turn off mobile data. onLost callback is triggered, but the network has internet.
override fun onLost(network: Network) {
super.onLost(network)
Timber.d("onLost")
val hasNet = connectivityManager
.getNetworkCapabilities(network)
?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
Timber.d("network $network, hasNet=$hasNet")
lastInternetConnectionCheck(network)
checkOld()
}@Suppress("DEPRECATION")
private fun checkOld() {
val hasConnection = connectivityManager.activeNetworkInfo?.isConnectedOrConnecting == true
Timber.d("Old check = $hasConnection")
}Output:
D/AndroidNetworkStateManager: onLost
D/AndroidNetworkStateManager: network 126, hasnet=true
D/AndroidNetworkStateManager: netInternet: true, WiFi: false, Cellular: true, Ethernet: false, VPN: false
D/AndroidNetworkStateManager: Connections State true
D/AndroidNetworkStateManager: Old check = false
@agvozditskiy Network might have an internet connection, but the device is not connected to the network anymore.
@agvozditskiy Network might have an internet connection, but the device is not connected to the network anymore.
@GokhanArik And how to track this state correct?
@agvozditskiy Check this gist, we discussed this there in detail: https://gist.github.com/PasanBhanu/730a32a9eeb180ec2950c172d54bb06a#gistcomment-3374351
I ended up using the new callback, and inside callback using deprecated methods to check -isConnectedOrconnecting()
@GokhanArik we use the same solution )
private fun setListeners() {
ConnectivityMonitor(this, this) { isConnected ->
//TODO whatever you need
}
}
getting isConnected true even I disabled cellular network,
@krb449 That behavior is coming from lastInternetConnectionCheck(). As long as any of the variables transportCellular, ... is true, netInternet will be true and toggleConnectionState/isConnected will be true. I think that also explains @agvozditskiy observation.
For my project, I just included only netInternet in isConnected and so far I have a consistent behavior.
val isConnected = netInternet
// ||transportWifi || transportCellular || transportEthernet || transportVpn
@iRYO400 Thanks for the code
Hello guys, allNetworks array become empty (zero size) when the connection is lost and the callback is not triggered, so the last function should be:
private fun lastInternetConnectionCheck() {
if (connectivityManager.allNetworks.size == 0) {
toggleConnectionState(false)
} else {
connectivityManager.allNetworks.forEach { network ->
network?.let {
connectivityManager.getNetworkCapabilities(it)
?.let { networkCapabilities ->
val netInternet =
networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
val transportCellular =
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
val transportWifi =
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
val transportEthernet =
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
val transportVpn =
networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)
val isConnected = netInternet ||
transportWifi || transportCellular ||
transportEthernet || transportVpn
Log.d("DEBUG", "Connections State $isConnected netInternet: $netInternet, WiFi: $transportWifi, Cellular: $transportCellular, Ethernet: $transportEthernet, VPN: $transportVpn")
toggleConnectionState(isConnected)
}
}
}
}
}
Seems this code is not working i have tried it but internet is not there then also private fun setListeners() {
ConnectivityMonitor(this, this) { isConnected ->
//TODO whatever you need
}
}
isConnected coming true
Example of usage in Activity
In Fragment