Skip to content

Instantly share code, notes, and snippets.

@shahzadansari
Created May 27, 2022 20:04
Show Gist options
  • Save shahzadansari/6b24317ad8bcd985a49ed273251c1d2e to your computer and use it in GitHub Desktop.
Save shahzadansari/6b24317ad8bcd985a49ed273251c1d2e to your computer and use it in GitHub Desktop.
A utility class for monitoring network connection in real-time with LiveData.
import android.content.Context
import android.content.Context.CONNECTIVITY_SERVICE
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import android.net.NetworkRequest
import android.util.Log
import androidx.lifecycle.LiveData
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.IOException
import java.net.InetSocketAddress
import javax.net.SocketFactory
// Inspired by Mitch Tabian - https://youtu.be/To9aHYD5OVk
const val TAG = "MyTagConnectionManager"
class ConnectionLiveData(context: Context) : LiveData<Boolean>() {
private lateinit var networkCallback: ConnectivityManager.NetworkCallback
private val connectivityManager =
context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
private val validNetworks: MutableSet<Network> = HashSet()
private fun checkValidNetworks() {
postValue(validNetworks.size > 0)
}
override fun onActive() {
networkCallback = createNetworkCallback()
val networkRequest = NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_INTERNET)
.build()
connectivityManager.registerNetworkCallback(networkRequest, networkCallback)
}
override fun onInactive() {
connectivityManager.unregisterNetworkCallback(networkCallback)
}
private fun createNetworkCallback() = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
Log.d(TAG, "onAvailable: $network")
val networkCapabilities = connectivityManager.getNetworkCapabilities(network)
val hasInternetCapability = networkCapabilities?.hasCapability(NET_CAPABILITY_INTERNET)
Log.d(TAG, "onAvailable: ${network}, $hasInternetCapability")
if (hasInternetCapability == true) {
// Check if this network actually has internet
CoroutineScope(Dispatchers.IO).launch {
val hasInternet = DoesNetworkHaveInternet.execute(network.socketFactory)
if (hasInternet) {
withContext(Dispatchers.Main) {
Log.d(TAG, "onAvailable: adding network. $network")
validNetworks.add(network)
checkValidNetworks()
}
}
}
}
}
override fun onLost(network: Network) {
Log.d(TAG, "onLost: $network")
validNetworks.remove(network)
checkValidNetworks()
}
}
object DoesNetworkHaveInternet {
fun execute(socketFactory: SocketFactory): Boolean {
// Make sure to execute this on a background thread.
return try {
Log.d(TAG, "PINGING Google...")
val socket = socketFactory.createSocket() ?: throw IOException("Socket is null.")
socket.connect(InetSocketAddress("8.8.8.8", 53), 1500)
socket.close()
Log.d(TAG, "PING success.")
true
} catch (e: IOException) {
Log.e(TAG, "No Internet Connection. $e")
false
}
}
}
}
private lateinit var connectionLiveData: ConnectionLiveData
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
.
.
.
connectionLiveData = ConnectionLiveData(this)
connectionLiveData.observe(this) { isNetworkAvailable ->
// TODO: updateUI(isNetworkAvailable)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment