首页 / Android 入门教程 / 有序广播与本地广播

Android 入门教程

有序广播与本地广播

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

AndroidAndroid 入门教程有序广播本地广播广播权限LocalBroadcastManager

36. 有序广播与本地广播

本节目标:分清普通广播、有序广播、本地广播三种类型的区别,学会用有序广播传递数据、用本地广播做应用内通信、用权限保护广播安全。

上一节我们接触的是「普通广播」—用 sendBroadcast() 发送,所有接收器几乎同时收到,互不影响。这节来看另外两种特殊广播。

有序广播

还是用比喻:普通广播像群发消息,大家同时收到各看各的;有序广播像传纸条,A 看完传给 B,B 看完传给 C,中途谁都能改内容,甚至能把纸条截下来不传了。

有序广播用 sendOrderedBroadcast() 发送,接收器按优先级逐个执行。每个接收器可以:

  • 读取上一个接收器传下来的结果
  • 修改或追加数据传给下一个
  • 调用 abortBroadcast() 终止广播,后面的接收器就收不到了

发送有序广播

val intent = Intent("com.example.app.ORDERED_ACTION").apply {
    putExtra("message", "原始消息")
    setPackage("com.example.app") // 限定包名
}
// 第二个参数是权限,传 null 表示不限制
context.sendOrderedBroadcast(intent, null)

设置优先级

优先级在 IntentFilter 里设置,数值越大越先收到:

val filter = IntentFilter("com.example.app.ORDERED_ACTION").apply {
    priority = 100 // 高优先级先收到
}
ContextCompat.registerReceiver(
    context, highPriorityReceiver, filter,
    ContextCompat.RECEIVER_NOT_EXPORTED
)

XML 里也能设置:

<intent-filter android:priority="100">
    <action android:name="com.example.app.ORDERED_ACTION" />
</intent-filter>
Warning

在 Android 16 中,跨进程的广播优先级已经不再保证顺序android:priority 只在同一应用进程内有效。如果你的多个接收器在同一应用里,优先级还有用;跨应用就别指望顺序了。

在接收器间传递数据

class FirstReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val msg = intent.getStringExtra("message")
        // 把结果传给下一个接收器
        setResultData("$msg -> 第一站处理完毕")
    }
}

class SecondReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        // 拿到上一个接收器传来的结果
        val previousResult = getResultData()
        Log.d("SecondReceiver", "收到: $previousResult")
        // 也可以终止广播,后面就收不到了
        // abortBroadcast()
    }
}

getResultData() / setResultData() 传递字符串,getResultExtras() / setResultExtras() 传递 Bundle,适合传复杂数据。

获取最终结果

如果只想知道最后一个接收器处理完的结果,可以用带 resultReceiver 参数的版本:

context.sendOrderedBroadcast(
    intent,
    null, // 权限
    finalReceiver, // 所有接收器跑完后再回调这个
    null, // Handler,null 表示主线程
    0,
    "初始数据",
    null
)

本地广播

普通广播有个问题:用 sendBroadcast() 发出去,其他应用也能收到。如果只是应用内部传消息,用普通广播既不安全(可能被别的应用截获),又低效(要跨进程)。

本地广播(Local Broadcast)就是解决这个问题的。它只在应用内部传递,不跨进程,收发都更快更安全。

用法

本地广播需要 androidx.localbroadcastmanager 库。先加依赖:

dependencies {
    implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.1.0")
}

发送本地广播:

val intent = Intent("com.example.app.LOCAL_ACTION").apply {
    putExtra("data", "应用内部消息")
}
LocalBroadcastManager.getInstance(context).sendBroadcast(intent)

注册接收器也要通过 LocalBroadcastManager

override fun onStart() {
    super.onStart()
    val filter = IntentFilter("com.example.app.LOCAL_ACTION")
    LocalBroadcastManager.getInstance(this)
        .registerReceiver(localReceiver, filter)
}

override fun onStop() {
    super.onStop()
    LocalBroadcastManager.getInstance(this)
        .unregisterReceiver(localReceiver)
}
Note

本地广播只能动态注册,不能在清单里声明。因为它不经过系统,系统不知道它的存在。

Warning

LocalBroadcastManager 已被官方标记为已废弃(deprecated)。官方推荐用 LiveDataFlow 或其他观察者模式替代。如果你的项目是新项目,建议直接用 Kotlin 的 StateFlow / SharedFlow 做应用内事件传递,比本地广播更现代。这里了解概念即可,老项目里可能还会碰到。

现代替代方案

既然本地广播废弃了,应用内通信该用什么?几个常见选择:

  • 简单事件通知:用 SharedFlow 发事件,UI 层用 collectAsState 收。
  • 状态同步:用 StateFlow 暴露状态,订阅者自动响应。
  • 跨组件通信:用 ViewModel 共享数据(第 41 章会讲)。
// 一个简单的应用内事件总线
object AppEvents {
    private val _events = MutableSharedFlow<String>()
    val events = _events.asSharedFlow()

    suspend fun emit(message: String) {
        _events.emit(message)
    }
}

广播权限

如果确实需要跨应用广播,又想限制谁能收发,可以用权限机制。

发送方限制接收方

发送时指定权限,只有声明了该权限的接收方才能收到:

context.sendBroadcast(
    intent,
    android.Manifest.permission.ACCESS_COARSE_LOCATION // 用系统权限举例
)

接收方清单里要声明对应权限:

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

接收方限制发送方

反过来,接收方也可以要求发送方必须持有某权限:

<receiver
    android:name=".MyReceiver"
    android:permission="android.permission.ACCESS_COARSE_LOCATION"
    android:exported="true">
    <intent-filter>
        <action android:name="com.example.app.PROTECTED_ACTION" />
    </intent-filter>
</receiver>

这样只有持有该权限的应用才能给这个接收器发广播,恶意应用发不了。

Tip

你也可以用 <permission> 标签自定义权限,而不只用系统预置的。自定义权限能精确控制「只有我家的几个应用能互相通信」。

三种广播对比

特性普通广播有序广播本地广播(已废弃)
发送方法sendBroadcast()sendOrderedBroadcast()LocalBroadcastManager.sendBroadcast()
接收顺序并行,无序按优先级顺序应用内,无跨进程
可中断是(abortBroadcast()
可传递结果
跨应用
安全性低(需手动加权限)

小结

有序广播适合需要按优先级处理、中途修改数据的场景,但 Android 16 后跨进程顺序不再保证。本地广播概念上很实用,但已废弃,新项目用 Flow 替代。跨应用广播务必加权限保护。日常开发里,绝大多数应用内通信用 Flow 就够了,广播主要用于接收系统事件。