首页 / Android 入门教程 / BroadcastReceiver

Android 入门教程

BroadcastReceiver

本教程共 100 篇 · 第 35 篇 · 更新于 2026-07-28 · 约 8 分钟阅读

AndroidAndroid 入门教程BroadcastReceiver广播接收器系统广播动态注册

35. BroadcastReceiver

本节目标:搞懂广播接收器是什么、怎么收系统广播、怎么发自定义广播,学完能在应用里监听飞行模式切换、电量变化等系统事件。

广播是什么

打个比方:广播就像小区里的广播喇叭。物业(系统)喊一声「停水通知」,所有装了对应喇叭(接收器)的住户都能听到。住户听到后各自决定干什么——有的去接水,有的只是记一下。

Android 里的广播(Broadcast)就是这种「一对多」的消息机制,遵循发布-订阅模式。系统在发生各种事件时会发广播,比如设备开机完成、飞行模式切换、电量不足。应用也可以发自己的广播,通知别的应用「我这有新数据了」。

广播接收器(BroadcastReceiver)就是那个「喇叭」,负责接收并处理这些消息。

两种注册方式

接收广播有两种方式,区别在于「喇叭装在哪」:

  • 静态注册(清单声明):在 AndroidManifest.xml 里用 <receiver> 标签声明。应用装上就生效,哪怕应用没运行,广播来了系统也能把应用拉起来。
  • 动态注册(上下文注册):在代码里调用 registerReceiver() 注册。只在注册期间有效,注册它的上下文(比如 Activity)销毁了就收不到了。
Warning

从 Android 8.0(API 26)开始,系统对静态注册做了限制:大多数隐式广播不能再通过清单声明接收。只有少数豁免广播(如 BOOT_COMPLETED)还能静态注册。所以现在主流做法是动态注册。

静态注册长什么样

先看清单里的声明:

<receiver
    android:name=".BootCompletedReceiver"
    android:exported="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

android:exported 设为 false 表示只接收应用自己发的广播。如果要收系统或其他应用的广播,设成 true

接收器类继承 BroadcastReceiver,实现 onReceive()

class BootCompletedReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
            // 开机完成后想做的事,比如启动一个定时任务
            Log.d("BootReceiver", "设备开机完成")
        }
    }
}
Note

开机广播需要 RECEIVE_BOOT_COMPLETED 权限,别忘了在清单里加上 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

动态注册实战:监听飞行模式

动态注册是日常用得最多的方式。下面监听飞行模式切换,用 Kotlin 写一个完整例子。

先创建接收器:

class AirplaneModeReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        // 飞行模式广播会带一个 "state" 布尔 extra
        val isAirplaneModeOn = intent.getBooleanExtra("state", false)
        if (isAirplaneModeOn) {
            Toast.makeText(context, "飞行模式已开启", Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(context, "飞行模式已关闭", Toast.LENGTH_SHORT).show()
        }
    }
}

在 Activity 里注册和注销:

class MainActivity : ComponentActivity() {

    private val receiver = AirplaneModeReceiver()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent { /* Compose 内容 */ }
    }

    override fun onStart() {
        super.onStart()
        val filter = IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)
        // Android 13+ 必须指定导出标志
        ContextCompat.registerReceiver(
            this,
            receiver,
            filter,
            ContextCompat.RECEIVER_NOT_EXPORTED
        )
    }

    override fun onStop() {
        super.onStop()
        unregisterReceiver(receiver)
    }
}
Tip

从 Android 13(API 33)开始,动态注册必须指定 RECEIVER_EXPORTEDRECEIVER_NOT_EXPORTED 标志,否则会崩溃。用 ContextCompat.registerReceiver() 可以兼容旧版本。只收自己应用发的广播用 RECEIVER_NOT_EXPORTED,要收系统或其他应用的广播用 RECEIVER_EXPORTED

注册时机的选择

动态注册要选对生命周期范围,原则是「只在真正需要时注册,不需要了立刻注销」。常见选择:

  • onStart() / onStop():界面可见时才接收。
  • onResume() / onPause():界面可交互时才接收。
  • onCreate() / onDestroy():整个 Activity 存活期间都接收。
Warning

一定要在对应的回调里注销接收器!忘了注销会导致内存泄漏——接收器持有 Activity 的引用,Activity 销毁了却回收不掉。在 onDestroy() 里注销,别在 onSaveInstanceState() 里,因为那个方法不一定被调用。

发送自定义广播

应用也能自己发广播。比如下载完数据后通知其他模块刷新。

val intent = Intent("com.example.app.DATA_UPDATED").apply {
    putExtra("extra_data", "新内容")
    // 限定只发给同一包名的应用,更安全
    setPackage("com.example.app")
}
context.sendBroadcast(intent)
Tip

发广播时用 setPackage() 限定包名是个好习惯。不加限制的话,任何应用都能收到你的广播,敏感信息可能泄露。

onReceive 的注意事项

onReceive() 运行在主线程,而且系统希望它快点执行完。一旦方法返回,系统可能随时回收进程。

所以有几条规矩:

  1. 别在 onReceive() 里做耗时操作(网络请求、大文件读写)。
  2. 需要耗时的话,调用 goAsync()PendingResult 传给后台线程,但也要在 10 秒内搞定。
  3. 别直接启动 Activity,推荐用通知代替。
override fun onReceive(context: Context, intent: Intent) {
    // goAsync 让广播在后台线程处理完才结束
    val pendingResult = goAsync()
    CoroutineScope(Dispatchers.IO).launch {
        try {
            // 耗时操作,比如存数据
            doSomeWork()
        } finally {
            pendingResult.finish() // 必须调用,否则系统会认为广播没处理完
        }
    }
}

常用系统广播

广播 Action触发时机
ACTION_BOOT_COMPLETED系统启动完成
ACTION_AIRPLANE_MODE_CHANGED飞行模式开关切换
ACTION_BATTERY_LOW电量不足
ACTION_TIME_TICK每分钟一次(只能动态注册)
CONNECTIVITY_ACTION网络连接变化(Android 7.0 起只能动态注册)
Note

随着版本演进,系统广播的行为一直在收紧。Android 16 中,跨进程的广播优先级不再保证顺序,只有同一进程内的优先级才生效。写代码时别依赖广播的接收顺序。

小结

广播接收器是 Android 四大组件之一,本质是一套发布-订阅消息机制。静态注册适合开机自启这类少数场景,动态注册是现在的主流。记住三件事:动态注册要配对注销、onReceive 要快、发广播要限定包名。