Android 广播(Broadcast Receiver)详解

广播(Broadcast)是 Android 系统中跨组件、跨应用通信的核心机制,允许应用监听系统或自定义事件并响应。本文从广播类型使用方式版本兼容注意事项典型场景五个维度全面解析。

一、广播类型与使用场景

广播类型 特点 适用场景
标准广播 完全异步,所有接收器同时接收,无法中断。 发送无需有序处理的事件(如自定义全局通知)。
有序广播 同步执行,接收器按优先级顺序处理,可中断传播。 需要拦截或修改广播结果的场景(如短信拦截)。
本地广播 仅应用内传播,通过 LocalBroadcastManager 实现,安全性高。 应用内部组件通信(如 Activity 与 Service 通信)。
系统广播 由系统触发,如网络状态变化、电量不足、时区变更等。 监听系统事件并响应(如网络恢复后自动同步数据)。
粘性广播 发送后仍保留在系统中,新注册的接收器仍能接收(Android 5.0+ 已废弃)。 旧版本兼容场景(已不推荐使用)。

二、广播的注册与发送方式

1、静态注册(Manifest 声明)

  • 特点 :在 AndroidManifest.xml 中声明,应用未启动也能接收广播(如监听开机完成)。

  • 代码示例

    xml 复制代码
    <receiver 
        android:name=".BootCompleteReceiver"
        android:exported="true"> <!-- 是否允许跨应用接收 -->
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
  • 注意事项

    • Android 8.0+ 限制静态注册的隐式广播(非应用专属广播),需使用显式 Intent 或动态注册。

2、动态注册(代码注册)

  • 特点:通过代码注册,灵活控制生命周期,需手动注销避免内存泄漏。

  • 代码示例

    kotlin 复制代码
    // 注册广播
    val filter = IntentFilter().apply {
        addAction("com.example.MY_CUSTOM_ACTION")
        addAction(ConnectivityManager.CONNECTIVITY_ACTION) // 网络变化
    }
    val receiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            when (intent?.action) {
                "com.example.MY_CUSTOM_ACTION" -> handleCustomAction()
                ConnectivityManager.CONNECTIVITY_ACTION -> handleNetworkChange()
            }
        }
    }
    context.registerReceiver(receiver, filter)
    
    // 注销广播(通常在 onDestroy 中调用)
    override fun onDestroy() {
        super.onDestroy()
        context.unregisterReceiver(receiver)
    }

3、发送广播

  • 标准广播

    kotlin 复制代码
    val intent = Intent("com.example.MY_CUSTOM_ACTION").apply {
        putExtra("data", "Hello, Broadcast!")
    }
    context.sendBroadcast(intent)
  • 有序广播

    kotlin 复制代码
    context.sendOrderedBroadcast(intent, null) // 第二个参数为权限

三、版本兼容性问题

版本 关键变更 适配方案
Android 7.0+ 禁止后台应用通过静态注册监听 CONNECTIVITY_ACTION 等隐式广播。 改用动态注册或 JobScheduler 监听网络状态。
Android 8.0+ 限制静态注册的隐式广播(需显式声明 package 或使用动态注册)。 静态注册时添加 android:exported="false" 或使用 Intent.setPackage() 指定包名。
Android 9.0+ 移除 WIFI_SCAN_AVAILABLEDEVICE_POWER_CONNECTED 等敏感广播的默认监听权限。 动态申请 ACCESS_FINE_LOCATION 等权限。
Android 10+ 限制后台应用启动 Activity,需在广播接收器中添加 FLAG_ACTIVITY_NEW_TASK 启动 Activity 时设置 Flag: intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

四、注意事项与最佳实践

1、安全性优化

  • 限制接收范围 :使用 android:permission 声明权限,避免恶意广播攻击。
xml 复制代码
<receiver android:name=".MyReceiver"
    android:permission="com.example.CUSTOM_PERMISSION">
    <intent-filter> ... </intent-filter>
</receiver>
  • 本地广播 :优先使用 LocalBroadcastManager(AndroidX 已废弃) 避免跨应用风险。

    • 推荐替代方案
      使用 LiveData 或事件总线(如 EventBusRxBus)。
kotlin 复制代码
LocalBroadcastManager.getInstance(context).sendBroadcast(intent)

2、性能优化

  • 避免主线程阻塞 :在 onReceive() 中禁止耗时操作,超过 10 秒会导致 ANR。

  • 异步处理 :使用 goAsync()(API 11+)或启动 Service 执行后台任务。

kotlin 复制代码
override fun onReceive(context: Context, intent: Intent) {
    val pendingResult = goAsync()
    thread {
        // 执行耗时操作
        pendingResult.finish()
    }
}        

3、内存泄漏预防

  • 及时注销动态广播 :在 Activity/FragmentonDestroy() 中调用 unregisterReceiver()

4、隐式广播限制规避

  • 显式指定包名:发送广播时指定目标应用包名。
kotlin 复制代码
intent.setPackage("com.example.targetapp")
context.sendBroadcast(intent)

五、典型使用场景

1、应用内组件通信

  • 场景:Activity 通知 Service 更新数据。
  • 方案 :使用 LocalBroadcastManager 发送本地广播。

2、监听系统事件

  • 场景:检测网络状态变化。

  • 代码示例

kotlin 复制代码
val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
context.registerReceiver(networkReceiver, filter)

3、跨应用通信

  • 场景:应用 A 触发应用 B 的特定功能。
  • 方案:发送带权限的显式广播,并在接收方声明相同权限。

六、常见问题与解决

1、接收不到广播

  • 检查 Intent 的 Action 是否一致。
  • 确认注册方式(静态/动态)是否匹配。
  • 高版本系统需适配隐式广播限制。

2、动态注册的广播在屏幕旋转后失效

  • onResume() 中注册,onPause() 中注销(根据业务需求调整生命周期)。

3、粘性广播无法使用

  • 替换为 LocalBroadcastManager 或事件总线库。

七、总结

场景 推荐方案 关键注意事项
应用内通信 LocalBroadcastManager 避免跨应用暴露广播 Action
监听系统事件 动态注册 + 权限检查 Android 7.0+ 需动态注册部分系统广播
跨应用触发功能 显式广播 + 自定义权限 接收方需声明相同权限并验证发送方身份
后台任务触发 WorkManager 替代广播 避免依赖广播执行后台耗时操作

通过合理选择广播类型、适配版本限制并遵循安全规范,可高效利用广播机制实现灵活通信,同时保障应用性能与安全性。

更多分享

  1. 一文带你吃透Android中Service的种类和启动方式
  2. 一文带你吃透Android中显示Intent与隐式Intent的区别
  3. Android中Binder通信的优势以及与传统IPC的差异
  4. 一文带你吃透Android 中 AIDL 与 bindService 的核心区别
相关推荐
小白学大数据33 分钟前
动态URL构建与HTTP请求的Kotlin实现
开发语言·爬虫·网络协议·http·kotlin
小墙程序员43 分钟前
一文了解 Android 中的 UID、GID、PID
android
&有梦想的咸鱼&2 小时前
Android Compose 框架文本选择与编辑模块源码深度剖析(三)
android
二流小码农3 小时前
鸿蒙开发:远场通信服务rcp会话问题
android·ios·harmonyos
SuperHeroWu74 小时前
【HarmonyOS Next】鸿蒙中App、HAP、HAR、HSP概念详解
华为·app·harmonyos·鸿蒙·har·hsp·hap
stevenzqzq5 小时前
kotlin @JvmStatic的使用
android·开发语言·kotlin
氦客5 小时前
Kotlin知识体系(二) : Kotlin的七个关键特性
android·开发语言·kotlin·安卓·特性·data class·密封类
阿豪元代码6 小时前
Perfetto 快速上手指南1 —— Trace 的抓取
android
&有梦想的咸鱼&6 小时前
Android Fresco 框架扩展模块源码深度剖析(四)
android
fatiaozhang95276 小时前
烽火HG680-KB_海思HI3798MV310_安卓9.0_U盘强刷固件包及注意点说明
android·华为·机顶盒rom·魔百盒刷机·移动魔百盒