Displaying a "No Internet" Bar Inside Your Android App
Whilst developing an app, you’re likely to have a strong, reliable data connection at all times. In the real world however, users often will be without connectivity, and your app should react appropriately.
In this tutorial, a simple animated “No internet is available” bar will be displayed inside the app whilst there is no internet, and disappear when connectivity returns. An example no internet bar project is available, as well as a video of the finished implementation.
Add network state permission
First, permission to access the network state is needed. This permission doesn’t need to be requested at runtime, and just being included in the AndroidManifest.xml
is sufficient:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Add bar to layout
Next, the bar has to actually be added to the layout. This can of course be customised easily, I’ve gone for a solid bright pink bar to grab attention!
<TextView
android:id="@+id/no_internet_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FF4081"
android:gravity="center_horizontal"
android:padding="5dp"
android:text="There is no internet connection available!"
android:textColor="#FFFFFF"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent" />
Create network receiver
NetworkReceiver.kt
is a small class that serves 3 functions:
- Checking the current internet status on demand:
private fun hasInternet(context: Context): Boolean { val connectMgr = (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager) val activeNetworkInfo = connectMgr.activeNetworkInfo return activeNetworkInfo != null &amp;&amp; activeNetworkInfo.isConnected }
- Providing an interface for activities to implement, so that it can broadcast network state change events:
interface NetworkReceiverListener { fun onNetworkConnectionChanged(isConnected: Boolean) } companion object { var networkReceiverListener: NetworkReceiverListener? = null }
- Actually broadcasting the events as they are received:
override fun onReceive(context: Context, arg1: Intent) { if (networkReceiverListener != null) { networkReceiverListener!!.onNetworkConnectionChanged(hasInternet(context)) } }
Setup network listener
Initialising the NetworkReceiver
‘s networkReceiverListener
hooks the activity into the broadcast receiver we just created. This should be done during onCreate()
or as early as possible:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setupNetworkListener()
}
private fun setupNetworkListener() {
NetworkReceiver.networkReceiverListener = object : NetworkReceiver.NetworkReceiverListener {
override fun onNetworkConnectionChanged(isConnected: Boolean) {
toggleNoInternetBar(!isConnected)
}
}
}
Hook into Android lifecycle events
Next, we need to make sure receivers are only registered whilst our activity is, otherwise we may continue listening to network events even after the app is closed. onStart
and onStop
should be used for registering and unregistering the receiver.
private var networkReceiver: NetworkReceiver? = null
override fun onStart() {
super.onStart()
networkReceiver = NetworkReceiver()
registerReceiver(networkReceiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
}
override fun onStop() {
super.onStop()
networkReceiver?.let { unregisterReceiver(it) }
}
Display bar
Finally, and most importantly, we need to actually show the bar! toggleNoInternetBar
is called when the network state changes, and accepts a boolean determining if the bar should be shown or hidden. Two simple animations are used to improve appearances:
enter_from_bottom.xml
is used for the bar appearing:<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> <translate android:duration="400" android:fromXDelta="0%" android:fromYDelta="100%" android:toXDelta="0%" android:toYDelta="0%" /> </set>
exit_to_bottom.xml
is used for the bar disappearing:<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:shareInterpolator="false"> <translate android:duration="400" android:fromXDelta="0%" android:fromYDelta="0%" android:toXDelta="0%" android:toYDelta="100%" /> </set>
Finally, these animations are used to toggle visibility:
private fun toggleNoInternetBar(display: Boolean) {
if (display) {
val enterAnim = AnimationUtils.loadAnimation(this, R.anim.enter_from_bottom)
no_internet_bar.startAnimation(enterAnim)
} else {
val exitAnim = AnimationUtils.loadAnimation(this, R.anim.exit_to_bottom)
no_internet_bar.startAnimation(exitAnim)
}
no_internet_bar.visibility = if (display) View.VISIBLE else View.GONE
}
Conclusion
For an internet-dependent app, the ability to show users a warning that the displayed data may not be up to date is an easy way to improve the user experience. Small features like this really add up, and can help persuade a user to feel positively towards your app / service.
One potentially unexpected quirk of the implementation in this tutorial that can cause issues during testing is the delay when disabling Airplane Mode. Once Airplane Mode is disabled, it can take 5-10 seconds until connectivity returns and the bar disappears.
An example no internet bar project has also been created for this tutorial.