Android
BroadcastReceiver
Internet Connection
App Development
Network Monitoring

Broadcast receiver for checking internet connection in android app

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Android apps often need to know when the device regains or loses internet connectivity so they can retry work, refresh data, or show offline UI. Older examples use a BroadcastReceiver for everything, but modern Android requires a more careful approach because background broadcast behavior changed over time. The right answer depends on whether you need screen-level updates or long-lived app-wide monitoring.

What a Broadcast Receiver Can Still Do Well

A BroadcastReceiver is useful when a visible screen wants short-lived connectivity updates. Register it dynamically while the UI is active, do a quick connectivity check, and then let the view model or repository decide what to do.

kotlin
1import android.content.BroadcastReceiver
2import android.content.Context
3import android.content.Intent
4import android.net.ConnectivityManager
5import android.net.NetworkCapabilities
6
7class ConnectivityReceiver(
8    private val onChanged: (Boolean) -> Unit
9) : BroadcastReceiver() {
10    override fun onReceive(context: Context, intent: Intent?) {
11        val manager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
12        val network = manager.activeNetwork
13        val caps = manager.getNetworkCapabilities(network)
14        val connected = caps?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) == true &&
15            caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
16        onChanged(connected)
17    }
18}

The important detail is checking for validated internet access, not just the presence of some network link.

Register It in the Right Lifecycle

For an activity or fragment, register in onStart and unregister in onStop.

kotlin
1import android.content.IntentFilter
2import android.net.ConnectivityManager
3import android.os.Bundle
4import android.widget.TextView
5import androidx.appcompat.app.AppCompatActivity
6
7class MainActivity : AppCompatActivity() {
8    private lateinit var receiver: ConnectivityReceiver
9    private lateinit var statusView: TextView
10
11    override fun onCreate(savedInstanceState: Bundle?) {
12        super.onCreate(savedInstanceState)
13        setContentView(R.layout.activity_main)
14        statusView = findViewById(R.id.statusText)
15        receiver = ConnectivityReceiver { connected ->
16            statusView.text = if (connected) "Online" else "Offline"
17        }
18    }
19
20    override fun onStart() {
21        super.onStart()
22        registerReceiver(receiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
23    }
24
25    override fun onStop() {
26        unregisterReceiver(receiver)
27        super.onStop()
28    }
29}

This keeps the receiver scoped to a visible screen and avoids leaks.

Why NetworkCallback Is Often Better

For modern Android, ConnectivityManager.NetworkCallback is usually a better long-term mechanism than relying only on connectivity broadcasts.

kotlin
1import android.content.Context
2import android.net.ConnectivityManager
3import android.net.Network
4import android.net.NetworkRequest
5
6class NetworkObserver(context: Context, private val onStatus: (String) -> Unit) {
7    private val manager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
8
9    private val callback = object : ConnectivityManager.NetworkCallback() {
10        override fun onAvailable(network: Network) {
11            onStatus("Online")
12        }
13
14        override fun onLost(network: Network) {
15            onStatus("Offline")
16        }
17    }
18
19    fun start() {
20        manager.registerNetworkCallback(NetworkRequest.Builder().build(), callback)
21    }
22
23    fun stop() {
24        manager.unregisterNetworkCallback(callback)
25    }
26}

Use this when you want a cleaner app-level observer rather than a broadcast-oriented pattern.

Manifest Permissions Still Matter

At minimum, declare network state permission:

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

ACCESS_NETWORK_STATE lets you inspect connectivity. INTERNET lets you perform network operations. They solve different problems.

Connect the Signal to Real App Behavior

Connectivity checks are only useful if they drive a sensible retry strategy. Good patterns include:

  • queue work locally while offline
  • retry sync when connectivity returns
  • show cached content immediately
  • keep side effects idempotent so reconnect events do not duplicate writes

Do not put heavy work directly inside onReceive. Use the receiver or callback to signal a higher-level component.

Common Pitfalls

  • Treating any active network as guaranteed internet access.
  • Registering receivers globally when the need is only screen-specific.
  • Doing database or network work directly inside onReceive.
  • Forgetting to unregister callbacks or receivers.
  • Relying on outdated connectivity-broadcast behavior for all Android versions.

Summary

  • A dynamic BroadcastReceiver is fine for short-lived UI connectivity updates.
  • 'NetworkCallback is often the better modern choice for ongoing monitoring.'
  • Check for validated internet access, not just link presence.
  • Keep receivers lightweight and let repositories or view models handle real work.
  • Pair connectivity events with an offline-first retry strategy instead of only showing a status label.

Course illustration
Course illustration

All Rights Reserved.