Broadcast Receivers for system events

Alex Chen Jan 2026
2 tabs
package com.example.myapp.receivers

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.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Build
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow

class NetworkChangeReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == ConnectivityManager.CONNECTIVITY_ACTION) {
            val isConnected = isNetworkAvailable(context)
            // Handle network change
            onNetworkChange(isConnected)
        }
    }

    private fun isNetworkAvailable(context: Context): Boolean {
        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
            as ConnectivityManager

        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val network = connectivityManager.activeNetwork ?: return false
            val capabilities = connectivityManager.getNetworkCapabilities(network)
                ?: return false
            capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        } else {
            @Suppress("DEPRECATION")
            val networkInfo = connectivityManager.activeNetworkInfo
            networkInfo?.isConnected == true
        }
    }

    private fun onNetworkChange(isConnected: Boolean) {
        // Notify app of network state change
    }

    companion object {
        fun observeNetworkChanges(context: Context): Flow<Boolean> = callbackFlow {
            val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE)
                as ConnectivityManager

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                val callback = object : ConnectivityManager.NetworkCallback() {
                    override fun onAvailable(network: Network) {
                        trySend(true)
                    }

                    override fun onLost(network: Network) {
                        trySend(false)
                    }
                }

                val request = NetworkRequest.Builder()
                    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                    .build()

                connectivityManager.registerNetworkCallback(request, callback)

                awaitClose {
                    connectivityManager.unregisterNetworkCallback(callback)
                }
            } else {
                val receiver = object : BroadcastReceiver() {
                    override fun onReceive(context: Context, intent: Intent) {
                        @Suppress("DEPRECATION")
                        val isConnected = connectivityManager.activeNetworkInfo?.isConnected == true
                        trySend(isConnected)
                    }
                }

                val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
                context.registerReceiver(receiver, filter)

                awaitClose {
                    context.unregisterReceiver(receiver)
                }
            }
        }
    }
}
2 files · kotlin Explain with highlit

BroadcastReceiver responds to system-wide or app-specific events. I register receivers statically in AndroidManifest or dynamically with registerReceiver(). The onReceive() method handles broadcasts—network changes, battery status, boot completed, SMS received. Ordered broadcasts allow priority and result propagation. Local broadcasts limit scope to app with LocalBroadcastManager. Permission requirements protect sensitive broadcasts. Background execution limits on Android 8+ require JobScheduler or WorkManager for most system events. Receivers enable responding to system state changes and inter-component communication. Common use cases include syncing on network availability, reacting to power changes, or handling custom app events.