Monitor network connectivity, and show a SnackBar when the connection is lost.
internal sealed class ConnectivityMonitor(
protected val connectivityManager: ConnectivityManager
) {
protected var callbackFunction: ((Boolean) -> Unit) = {}
abstract fun startListening(callback: (Boolean) -> Unit)
abstract fun stopListening()
@TargetApi(Build.VERSION_CODES.N)
private class NougatConnectivityMonitor(connectivityManager: ConnectivityManager) :
ConnectivityMonitor(connectivityManager) {
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
callbackFunction(true)
}
override fun onLost(network: Network) {
super.onLost(network)
callbackFunction(false)
}
}
override fun startListening(callback: (Boolean) -> Unit) {
callbackFunction = callback
callbackFunction(false)
connectivityManager.registerDefaultNetworkCallback(networkCallback)
}
override fun stopListening() {
connectivityManager.unregisterNetworkCallback(networkCallback)
callbackFunction = {}
}
}
@Suppress("Deprecation")
private class LegacyConnectivityMonitor(
private val context: Context,
connectivityManager: ConnectivityManager
) : ConnectivityMonitor(connectivityManager) {
private val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
private val isNetworkConnected: Boolean
get() = connectivityManager.activeNetworkInfo?.isConnected == true
override fun startListening(callback: (Boolean) -> Unit) {
callbackFunction = callback
callbackFunction(isNetworkConnected)
context.registerReceiver(receiver, filter)
}
override fun stopListening() {
context.unregisterReceiver(receiver)
callbackFunction = {}
}
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
callbackFunction(isNetworkConnected)
}
}
}
companion object {
fun getInstance(context: Context): ConnectivityMonitor {
val connectivityManager =
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
NougatConnectivityMonitor(
connectivityManager
)
} else {
LegacyConnectivityMonitor(
context,
connectivityManager
)
}
}
}
}
enum class ConnectivityState {
Connected,
Disconnected
}
class ConnectivityLiveData :
MutableLiveData<ConnectivityState>(), KoinComponent {
private val connectionMonitor: ConnectivityMonitor by inject()
override fun onActive() {
super.onActive()
connectionMonitor.startListening(::setConnected)
}
override fun onInactive() {
connectionMonitor.stopListening()
super.onInactive()
}
private fun setConnected(isConnected: Boolean) =
postValue(if (isConnected) ConnectivityState.Connected else ConnectivityState.Disconnected)
}
Usage
Sample usage using Koin DI:
class MainActivity : AppCompatActivity() {
val connectivity: ConnectivityLiveData by inject()
override fun onCreate(savedInstanceState: Bundle?) {
...
connectivity.observeForever { state ->
if (state != ConnectivityState.Connected) {
showSnackbar(R.string.no_internet)
} else {
hideSnackbar()
}
}
}
fun showSnackbar(error: Int) {
snackbar =
Snackbar.make(activity_parent, error, Snackbar.LENGTH_INDEFINITE)
snackbar?.let {
snackbar!!.setAction(R.string.label_Ok) { snackbar!!.dismiss() }
snackbar!!.show()
}
}
fun hideSnackbar() {
if (snackbar != null) {
if (snackbar!!.isShown) snackbar!!.dismiss()
}
}
}