Check Internet Connection in Android using BroadcastReceiver

Hello Developer, If you want to Check internet connection in Android using BroadcastReceiver Throughout the Application, so this post for you. In this post, we’ll be discussing about how we will check Internet Connection continuously in Android Studio Throughout the Application using Kotlin (step by step).

If there are any changes happen in the internet connection, the observer will continuously checking internet connection and it will return the Boolean value as per the network connection state.

I’ll share the way to monitor the Network Connection Continuously in the Activity/Fragment using Network Callback with the LiveData Observer. So without any further delay, let’s see step-by-step πŸ™‚

Continuously Check internet connection in Android using BroadcastReceiver

Step 1: First, create a new project

  • Open Android Studio.
  • Create a new project.
  • Filling in the project details.
  • Click on finish, now your project is successfully created.

Step 2: Add Permission

Now open Android Manifest, and add the most 2 important permission.

 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 <uses-permission android:name="android.permission.INTERNET" />

Step 3: Create a network_error XML layout

Create a new XML layout for showing network error design, when you go offline.

  • Go to res
  • layout
  • Right click on layout and select new then select Layout Resource File
  • Give name as network_error.xml and click OK.

network_error.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:orientation="vertical"
    android:padding="@dimen/dp_16">

    <ImageView
        android:id="@+id/errorImageView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_24"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/ic_no_internet"
        tools:ignore="ContentDescription" />

    <TextView
        android:id="@+id/errorTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_24"
        android:background="@drawable/layout_rounded_shape_light_red"
        android:gravity="center"
        android:padding="@dimen/dp_8"
        android:text="@string/network_error"
        android:textColor="@color/white"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/errorImageView" />

    <TextView
        android:id="@+id/errormsgTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:layout_marginBottom="@dimen/dp_8"
        android:gravity="center"
        android:text="@string/network_error_msg"
        android:textColor="@color/black"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/errorTextView" />
</androidx.constraintlayout.widget.ConstraintLayout>

Step 3.1: Create a new XML layout name as network_back_online_layout

Create a new XML layout for showing network online design.

  • Go to res
  • layout
  • Right click on layout and select new then select Layout Resource File
  • Give name as network_back_online_layout.xml and click OK.

network_back_online_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:orientation="vertical"
    android:padding="@dimen/dp_16">

    <TextView
        android:id="@+id/errorTextView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/dp_24"
        android:layout_marginBottom="@dimen/dp_24"
        android:background="@drawable/layout_rounded_shape_light_green"
        android:gravity="center"
        android:padding="@dimen/dp_8"
        android:text="We are back online."
        android:textColor="@color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Step 3.2: Create a new XML layout name as network_offline_online_layout

Finally, create a new XML layout for offline and online layout, we will add both XML layout in single a layout using include.

  • Go to res
  • layout
  • Right click on layout and select new then select Layout Resource File
  • Give name as network_offline_online_layout.xml and click ok.

network_offline_online_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:elevation="16dp"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/disable_all_views"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:animateLayoutChanges="true"
        android:background="@color/transfarent"
        android:gravity="bottom"
        android:orientation="vertical"
        android:visibility="gone">

        <LinearLayout
            android:id="@+id/layoutNetworkError"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <include layout="@layout/network_error" />
        </LinearLayout>
    </LinearLayout>

    <LinearLayout
        android:id="@+id/layoutNetworkBackOnline"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:animateLayoutChanges="true"
        android:gravity="bottom"
        android:orientation="vertical"
        android:visibility="gone">
        <include layout="@layout/network_back_online_layout" />
    </LinearLayout>
</LinearLayout>

Now design part is completed, let’s move to the main part to check the internet connection continuously.

Step 4: Create a Class name as DialogUtils.kt

This class will be responsible to keep you all utils related things like enable/disable View, show Network Error and show Network Back Online.

DialogUtils.kt

package com.techpassmaster.checkinternetconnection

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.view.View
import android.view.ViewGroup
import androidx.transition.Fade
import androidx.transition.Transition
import androidx.transition.TransitionManager
import gone
import visible

class DialogUtils {

    companion object {

        private var animationDuration: Long = 1500
        private var animAlphaHide = 0.0f
        private var animAlphaUnhide = 1.0f

        fun enableDisableView(v: View, enabled: Boolean) {
            if (v is ViewGroup) {
                val vg = v
                for (i in 0 until vg.childCount) {
                    enableDisableView(vg.getChildAt(i), enabled)
                }
            }
            v.isEnabled = enabled
        }


        fun showNetworkError(offlineView: ViewGroup, onlineView: ViewGroup) {

            onlineView.apply {
                animate()
                    .alpha(animAlphaUnhide)
            }

            val transition: Transition = Fade().apply {
                duration = animationDuration
                addTarget(offlineView)
            }
            TransitionManager.beginDelayedTransition(offlineView, transition)

            offlineView.visible()
        }

        fun showNetworkBackOnline(offlineView: ViewGroup, onlineView: View) {
            onlineView.apply {
                visible()
                animate()
                    .alpha(animAlphaHide)
                    .setDuration(animationDuration)
                    .setListener(object : AnimatorListenerAdapter() {
                        override fun onAnimationEnd(animation: Animator) {
                            onlineView.gone()
                        }
                    })
            }
            offlineView.gone()
        }
    }
}

Step 5: Create a new Kotlin Class name as BaseNetworkConnectionObserver

  • Create connectivityManager which will be extending ConnectivityManager and it is responsible for Monitor network connection,
  • Attempt to fail network when connectivity to a network is lost and etc and also you have to create a networkConnectionCallback variable for NetworkCallback in which you have to get two callbacks:
  1. onLost
  2. onAvailable
  • Create connectivityManagerCallback function for post the false value, when the connection is lost, and post true value when the internet is available.
  • Now create the updateNetworkConnection function which is used to post the true value and the internet is connected and also creates a variable that overrides the onReceive function and it is responsible to update Network Connection.

So this is the last step, just you have to override two functions.

  • onActive
  • onInactive

Below are the complete code:

BaseNetworkConnectionObserver.kt

package com.techpassmaster.checkinternetconnection

import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkInfo
import android.os.Build
import android.util.Log
import androidx.lifecycle.LiveData

class BaseNetworkConnectionObserver(private val context: Context) : LiveData<Boolean>() {

    private val connectivityManager: ConnectivityManager =
        context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    private var networkConnectionCallback: ConnectivityManager.NetworkCallback? = null
    private var isLost = false

    @SuppressLint("MissingPermission")
    override fun onActive() {
        super.onActive()

        try {
            updateNetworkConnection()
            when {
                Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> {
                    connectivityManager.registerDefaultNetworkCallback(connectivityManagerCallback())
                }
                else -> {
                    context.registerReceiver(
                        networkReceiver,
                        IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
                    )
                }
            }

        } catch (e: Exception) {
            Log.d("ExceptionMsg", e.toString())
        }
    }

    override fun onInactive() {
        super.onInactive()
        if (networkConnectionCallback != null && connectivityManager != null) {
            try {
                connectivityManager.unregisterNetworkCallback(networkConnectionCallback!!)
                // Added code: Set call back to null so this doesn't get called again.
                networkConnectionCallback = null
            } catch (e: java.lang.Exception) {
                Log.d("ExceptionMsg", e.toString())
            }
        }
    }

    private fun connectivityManagerCallback(): ConnectivityManager.NetworkCallback {
        networkConnectionCallback = object : ConnectivityManager.NetworkCallback() {
            @SuppressLint("MissingPermission")

            override fun onLost(network: Network) {
                super.onLost(network)

                postValue(false)
                isLost = true
            }

            override fun onAvailable(network: Network) {
                super.onAvailable(network)

                if (isLost) {
                    postValue(true)
                }
                isLost = false
            }
        }
        return networkConnectionCallback as ConnectivityManager.NetworkCallback
    }

    private val networkReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            try {
                updateNetworkConnection()
            } catch (e: Exception) {
                Log.d("BroadcastOnReceiver", e.toString())
            }
        }
    }

    @SuppressLint("MissingPermission")
    private fun updateNetworkConnection() {
        try {
            val activeNetworkConnection: NetworkInfo? = connectivityManager.activeNetworkInfo
            if (isLost) {
                postValue(activeNetworkConnection?.isConnected == true)
            }
        } catch (e: Exception) {
            Log.d("ExceptionMsg", e.toString())
        }
    }
}

Step 6: Create abstract Base Activity Class

If you want to use internet observer in Activity, so create a abstract BaseActivity.kt class. This base class, we will extend in the activity.

BaseActivity.kt

package com.techpassmaster.checkinternetconnection

import android.content.Context
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.LayoutInflater
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.postDelayed
import com.techpassmaster.checkinternetconnection.R
import com.techpassmaster.checkinternetconnection.databinding.NetworkOfflineOnlineLayoutBinding
import com.techpassmaster.checkinternetconnection.utils.dialog.DialogUtils
import com.google.android.material.bottomsheet.BottomSheetDialog

abstract class BaseActivity : AppCompatActivity() {
    
    companion object {
        val tag: String = BaseActivity::class.java.simpleName
    }

    // network connection
    private lateinit var networkErrorWithDisableAllViews: LinearLayout
    private lateinit var networkBackOnline: LinearLayout
    private lateinit var bottomSheetDialogOffline: BottomSheetDialog
    private lateinit var bottomSheetDialogOnline: BottomSheetDialog
    private lateinit var networkConnection: BaseNetworkConnectionObserver


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        networkConnection = BaseNetworkConnectionObserver(this)
        networkConnection.observe(this) { isConnected ->
            if (isConnected != null) {
                if (isConnected) {
                    isNetworkConnectionOn(this@BaseActivity)
                    isInternetOnCallApisAndInitUI()
                } else {
                    isNetworkConnectionOff(this@BaseActivity)
                }
            }
        }
    }

    abstract fun isInternetOnCallApisAndInitUI()

    private fun isNetworkConnectionOff(context: Context) {
        bottomSheetDialogOffline = BottomSheetDialog(context, R.style.BottomSheetDialog)
        val binding = NetworkOfflineOnlineLayoutBinding.inflate(LayoutInflater.from(context))
        bottomSheetDialogOffline.setContentView(binding.root)
        bottomSheetDialogOffline.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))

        networkErrorWithDisableAllViews = binding.disableAllViews
        networkBackOnline = binding.layoutNetworkBackOnline

        DialogUtils.showNetworkError(networkErrorWithDisableAllViews, networkBackOnline)

        bottomSheetDialogOffline.setCancelable(false)

        isNetworkConnectionOn(context)
        bottomSheetDialogOffline.show()
    }

    private fun isNetworkConnectionOn(context: Context) {

        bottomSheetDialogOffline.dismiss()

        bottomSheetDialogOnline = BottomSheetDialog(context, R.style.BottomSheetDialog)
        val binding = NetworkOfflineOnlineLayoutBinding.inflate(LayoutInflater.from(context))
        bottomSheetDialogOnline.setContentView(binding.root)

        networkErrorWithDisableAllViews = binding.disableAllViews
        networkBackOnline = binding.layoutNetworkBackOnline
        DialogUtils.showNetworkBackOnline(networkErrorWithDisableAllViews, networkBackOnline)

        DialogUtils.enableDisableView(binding.root, true)

        Handler(Looper.getMainLooper()).postDelayed(1500) {
            bottomSheetDialogOnline.dismiss()
        }

        bottomSheetDialogOnline.setCancelable(true)
        bottomSheetDialogOnline.show()
    }
}

Step 6.1: Observe Internet in the Activity

Here you will see, we are extending the BaseActivity() and after extending the BaseActivity(), you have to override a method isInternetOnCallApisAndInitUI.

In isInternetOnCallApisAndInitUI you can re-call & re-init your API’s and UI.

package com.techpassmaster.checkinternetconnection

import android.os.Bundle
import com.techpassmaster.checkinternetconnection.BaseActivity
import com.techpassmaster.checkinternetconnection.ActivityMainBinding

class MainActivity : BaseActivity() {

    private lateinit var activityMainBinding: ActivityMainBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
       
        activityMainBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(activityMainBinding.root)
    }

    override fun isInternetOnCallApisAndInitUI() {
        // here re-call & re-init your api's and UI
    }
}

Step 7: Create abstract Base Fragment class

If you want to use internet observer in Fragment, so create a abstract BaseFragment.kt class. This base class, we will extend in the fragment.

BaseFragment.kt

package com.techpassmaster.checkinternetconnection

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment

abstract class BaseFragment : Fragment() {

    private lateinit var networkConnection: BaseNetworkConnectionObserver
    
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return super.onCreateView(inflater, container, savedInstanceState)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        networkConnection = BaseNetworkConnectionObserver(requireActivity())
        networkConnection.observe(requireActivity()) { isConnected ->
            if (isConnected != null) {
                if (isConnected) {
                    isInternetOnCallApisAndInitUI()
                }
            }
        }
    }

    abstract fun isInternetOnCallApisAndInitUI()
    
}

Step 7.1: Observe Internet in the Fragment

You need to do as we did in case of Activity (Extend Fragment class to BaseFragment() and override method).

package com.techpassmaster.checkinternetconnection

import android.os.Bundle
import com.techpassmaster.checkinternetconnection.BaseFragment
import com.techpassmaster.checkinternetconnection.FragmentMainBinding

class MainFragment : BaseFragment() {

    private lateinit var fragmentMainBinding: FragmentMainBinding
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
       
        fragmentMainBinding = FragmentMainBinding.inflate(layoutInflater)
        setContentView(activityMainBinding.root)
    }

    override fun isInternetOnCallApisAndInitUI() {
        // here re-call & re-init your api's and UI
    }
}

Finally, we did it. Just run and test your app. πŸ™‚

I hope you liked the post. If you have any questions regarding this post. Feel free to comment and share the post with other developers.
Happy Learning!!! :)
Recommended Reading:

Leave a Reply

Your email address will not be published. Required fields are marked *