My example implementation, the notifications of network status with Snackbar in Kotlin. Maybe it will help someone. I did the listener the status of the network. Snackbar POPs up on any screen!
interface INetworkAvailabilityNotification {
fun init()
}
class NetworkAvailabilityNotificationImpl(
val context: Context,
private val networkStateProvider: INetworkStateProvider,
resourcesInteractor: IResourcesInteractor) : INetworkAvailabilityNotification {
private var weekReferenceActivity: WeakReference<Activity>? = null
private var snackbar: Snackbar? = null
private val networkUnavailableText: String by lazy { resourcesInteractor.getString(R.string.network_unavailable_error) }
override fun init() {
initActivityCallback()
initOnlineListener()
}
private fun showSnackbar(message: String) {
initSnackBar()
setText(message)
snackbar?.show()
}
private fun setViewParams() {
snackbar?.let {
val layoutParams =
(it.view.layoutParams as FrameLayout.LayoutParams)
.also { lp -> lp.setMargins(0, 0, 0, 0) }
it.view.setBackgroundColor(Color.BLACK)
it.view.layoutParams = layoutParams
it.view.alpha = 0.90f
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
it.view.elevation = 0f
}
}
}
private fun initActivityCallback() = (context as? Application)?.registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacksImpl() {
override fun onActivityResumed(activity: Activity?) {
activity?.let { weekReferenceActivity = WeakReference(activity) }
}
})
private fun initSnackBar() = weekReferenceActivity?.get()?.findViewById<View>(android.R.id.content)?.let { view ->
if (weekReferenceActivity?.get() is AppCompatActivity) {
snackbar = Snackbar.make(view, "", Snackbar.LENGTH_INDEFINITE).setBehavior(NoSwipeBehavior())
setViewParams()
}
}
private fun initOnlineListener() {
networkStateProvider.isOnline.observe { isOnline ->
if (isOnline) snackbar?.dismiss() else showSnackbar(networkUnavailableText)
}
}
private fun setText(message: String) {
val spannableString = SpannableString(message).apply {
setSpan(ForegroundColorSpan(ContextCompat.getColor(context, R.color.white)), 0, message.length, 0)
}
snackbar?.setText(spannableString)
}
}
internal class NoSwipeBehavior : BaseTransientBottomBar.Behavior() {
override fun canSwipeDismissView(child: View): Boolean = false
}
open class ActivityLifecycleCallbacksImpl : Application.ActivityLifecycleCallbacks {
override fun onActivityPaused(activity: Activity?) {}
override fun onActivityResumed(activity: Activity?) {}
override fun onActivityStarted(activity: Activity?) {}
override fun onActivityDestroyed(activity: Activity?) {}
override fun onActivitySaveInstanceState(activity: Activity?, outState: Bundle?) {}
override fun onActivityStopped(activity: Activity?) {}
override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) {}
}
Network status class
interface INetworkStateProvider {
val stateLiveData: LiveData<SealedNetworkState>
val isOnline: LiveData<Boolean>
}
class NetworkStateProviderImpl(private val context: Context) : INetworkStateProvider {
private companion object {
const val CONNECTIVITY_CHANGE = "android.net.conn.CONNECTIVITY_CHANGE"
const val WIFI_STATE_CHANGED = "android.net.wifi.WIFI_STATE_CHANGED"
}
private val connectivityManager: ConnectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
private val broadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) = this@NetworkStateProviderImpl.onReceive()
}
override val stateLiveData: MutableLiveData<SealedNetworkState> = object : MutableLiveData<SealedNetworkState>() {
override fun onActive() = registerBroadcastReceiver()
override fun onInactive() = unregisterBroadcastReceiver()
}
override val isOnline: MutableLiveData<Boolean> = stateLiveData.map {
connectivityManager.activeNetworkInfo?.isConnected == true
}.distinctUntilChanged()
private fun registerBroadcastReceiver() {
context.registerReceiver(broadcastReceiver, IntentFilter().apply {
addAction(CONNECTIVITY_CHANGE)
addAction(WIFI_STATE_CHANGED)
})
}
private fun unregisterBroadcastReceiver() = context.unregisterReceiver(broadcastReceiver)
private fun getConnectivityStatus(): SealedNetworkState = if (connectivityManager.activeNetworkInfo?.isConnected == true) {
when (connectivityManager.activeNetworkInfo?.type) {
ConnectivityManager.TYPE_WIFI -> SealedNetworkState.NetworkWiFi
ConnectivityManager.TYPE_MOBILE -> SealedNetworkState.NetworkMobile
else -> SealedNetworkState.NetworkOther
}
} else SealedNetworkState.NetworkNone
private fun onReceive() = with(getConnectivityStatus()) {
if (this != stateLiveData.value) stateLiveData.postValue(this)
}
}
sealed class SealedNetworkState {
object NetworkWiFi : SealedNetworkState()
object NetworkMobile : SealedNetworkState()
object NetworkOther : SealedNetworkState()
object NetworkNone : SealedNetworkState()
}