Created
April 30, 2020 09:41
-
-
Save iRYO400/5da269f4d5edbc365c952bdcbdfe6b68 to your computer and use it in GitHub Desktop.
Check Internet Connection [API21+][API29+ supported] Lifecycle aware
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} | |
} | |
} | |
} |
@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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@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