Android Broadcast全面解析
2026/5/31 7:58:51 网站建设 项目流程

在安卓开发中,广播(Broadcast)是组件间通信的核心机制之一,它像一个“系统公告栏”,允许应用内组件、甚至跨应用间通过“发布-订阅”模式传递消息。无论是监听网络变化、接收开机完成事件,还是实现应用内模块通信,广播都扮演着重要角色。但广播的使用看似简单,实则暗藏诸多细节。

一、广播是什么、广播的作用

1. 广播的定义

广播是安卓系统提供的一种跨组件、跨进程的通信机制。其核心思想是“事件驱动”:当某个事件发生时(如网络断开、电量低、应用安装),事件源(广播发送者)会发送一条广播消息,系统中所有注册了该广播的接收者(BroadcastReceiver)都会收到这条消息,并执行相应的逻辑。

2. 广播的核心角色

  • 广播发送者(Sender):发起广播的角色,可以是系统组件(如系统服务)、第三方应用,也可以是自身应用的Activity、Service等。发送广播的本质是通过Intent携带消息,并调用系统API发送。

  • 广播接收者(Receiver):监听并处理广播的组件,必须继承BroadcastReceiver类,并重写onReceive(Context, Intent)方法——这是接收广播后的核心处理逻辑入口。

  • 系统服务(AMS):Activity Manager Service,作为“中介”负责管理广播的发送与匹配。发送者将广播交给AMS,AMS根据广播的Action、权限等信息,匹配所有符合条件的接收者,再将广播分发给它们。

3. 广播的核心价值

  • 解耦组件通信:发送者无需知道接收者的存在,接收者也无需依赖发送者,二者通过“事件”间接通信,降低组件耦合度。例如,应用的支付模块发送“支付成功”广播,订单模块、消息模块只需注册该广播即可响应,无需与支付模块直接关联。

  • 监听系统事件:这是广播最常用的场景。系统会在特定事件发生时发送预设广播,应用通过接收这些广播实现对系统状态的感知,如监听网络变化、屏幕点亮/熄灭、电池电量等。

  • 跨进程通信:广播天然支持跨进程传递,例如系统的“应用安装完成”广播,所有监听该事件的应用都能收到,实现跨应用的协同。

二、广播的分类

1. 按发送方式:有序广播 vs 无序广播

特性

无序广播(Normal Broadcast)

有序广播(Ordered Broadcast)

传递顺序

所有接收者同时接收,无固定顺序

按接收者优先级排序,从高到低依次传递

截断能力

无法截断,所有接收者都能收到

优先级高的接收者可调用abortBroadcast()截断,后续接收者收不到

数据传递

接收者无法修改广播数据

优先级高的接收者可通过setResultData()修改数据,传递给后续接收者

发送API

sendBroadcast(Intent)

sendOrderedBroadcast(Intent, String)

适用场景

通知类消息,如“新消息提醒”“天气更新”

需要按顺序处理的场景,如短信拦截、权限验证

2. 按作用范围:全局广播 vs 本地广播

全局广播(Global Broadcast):

  • 特性:广播可被系统中所有应用的接收者监听,也可发送给所有应用。
  • 风险:存在安全隐患(如敏感数据通过广播泄露)和性能问题(过多应用监听可能导致广播延迟)。
  • 适用场景:跨应用通信、监听系统事件。

本地广播(Local Broadcast):

  • 特性:广播仅在当前应用内部传递,无法跨进程,由LocalBroadcastManager管理。
  • 优势:安全性高(避免数据泄露)、效率高(无需跨进程通信)、无ANR风险(内部使用Handler机制)。
  • 适用场景:应用内组件间通信,如Activity向Service发送指令、Fragment与Activity传递消息。

3. 按发送者:系统广播 vs 自定义广播

系统广播(System Broadcast):系统预定义的广播,由系统组件发送,对应特定系统事件。例如:
网络变化:android.net.conn.CONNECTIVITY_CHANGE
开机完成:android.intent.action.BOOT_COMPLETED
电量低:android.intent.action.BATTERY_LOW

自定义广播(Custom Broadcast):开发者自行定义Action的广播,用于应用内或跨应用的自定义事件传递。例如,应用内“支付成功”广播,Action可定义为com.example.app.PAY_SUCCESS

三、广播接收者

广播接收者(BroadcastReceiver)是处理广播的核心,其使用流程分为“定义接收者”“注册广播”“处理广播”三步,其中“注册”是关键——安卓提供两种注册方式,各有适用场景。

1. 定义广播接收者

无论哪种注册方式,接收者的定义逻辑一致:继承BroadcastReceiver,重写onReceive()方法。

// 自定义广播接收者 public class MyBroadcastReceiver extends BroadcastReceiver { // 广播接收后回调此方法 @Override public void onReceive(Context context, Intent intent) { // 1. 获取广播携带的数据 String action = intent.getAction(); String data = intent.getStringExtra("key"); // 2. 根据Action区分不同广播,执行对应逻辑 if ("com.example.app.PAY_SUCCESS".equals(action)) { // 处理支付成功逻辑:更新订单状态、提示用户等 Toast.makeText(context, "支付成功:" + data, Toast.LENGTH_SHORT).show(); } else if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action)) { // 处理网络变化逻辑 checkNetworkState(context); } } // 示例:检查网络状态 private void checkNetworkState(Context context) { ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo info = cm.getActiveNetworkInfo(); if (info != null && info.isConnected()) { Toast.makeText(context, "网络已连接", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context, "网络已断开", Toast.LENGTH_SHORT).show(); } } }

注意:onReceive()方法运行在主线程(UI线程)中,不能执行耗时操作(超过10秒会触发ANR)。若需处理耗时逻辑,需启动Service或使用WorkManager,不能直接在该方法中开线程(线程可能被系统回收)。

2. 注册广播(核心)

广播接收者必须注册后才能接收广播,注册分为“静态注册”和“动态注册”,二者的核心差异在于“注册时机”和“生命周期关联”。

方式一:静态注册(AndroidManifest注册)

AndroidManifest.xml中配置接收者,属于“全局注册”,应用未启动时也能接收广播。

<application ...> <receiver android:name=".MyBroadcastReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="com.example.app.PAY_SUCCESS" /> <action android:name="android.net.conn.CONNECTIVITY_CHANGE" /> </intent-filter> </receiver> </application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

说明:

  • enabled:控制接收者是否启用,若为false,即使注册也无法接收广播。
  • exported:控制是否允许接收其他应用的广播。若为false,仅能接收自身应用发送的广播,提升安全性。
  • 适用场景:适用于需要在应用未启动时接收的特殊系统广播,如开机完成、应用安装/卸载等。
  • API 26后的限制:为了优化系统性能,Android8.0(API 26)后,除少数特殊系统广播外静态注册的接收者无法接收普通广播。

方式二:动态注册(代码注册)

在Activity、Service等组件的代码中通过registerReceiver()注册,广播接收者的生命周期与注册组件绑定,组件销毁前必须注销,否则会导致内存泄漏。

public class MainActivity extends AppCompatActivity { private MyBroadcastReceiver myReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 1. 初始化接收者 myReceiver = new MyBroadcastReceiver(); // 2. 配置接收的广播Action IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("com.example.app.PAY_SUCCESS"); // 自定义广播 intentFilter.addAction(ConnectivityManager.CONNECTIVITY_CHANGE); // 系统广播 // 若为有序广播,可设置优先级(-1000~1000,数值越大优先级越高) intentFilter.setPriority(100); // 3. 注册广播 registerReceiver(myReceiver, intentFilter); } @Override protected void onDestroy() { super.onDestroy(); // 4. 必须注销广播,避免内存泄漏 unregisterReceiver(myReceiver); } }

注册后,只有当组件(如Activity)处于运行状态时,接收者才能接收广播;组件销毁前必须调用unregisterReceiver()注销,否则系统会抛出IllegalArgumentException。但现在推荐使用 LiveData、SharedFlow(Kotlin)或 EventBus 来替代应用内的本地广播通信。

综上我们可以总结出两种注册方式的区别:

对比维度

静态注册

动态注册

注册时机

应用安装时由系统完成注册

组件运行时(如onCreate)手动注册

应用未启动时

可接收广播(API 26前)

无法接收

生命周期

与应用绑定,除非卸载或禁用

与注册组件绑定,组件销毁需注销

API 26兼容性

大部分广播失效

完全兼容

灵活性

低,无法动态修改

高,可动态添加/移除Action

3. 发送广播

发送广播的核心是通过Intent指定广播的Action和携带数据,再调用对应的发送API。

发送无序广播

// 1. 构建Intent,指定广播Action Intent intent = new Intent("com.example.app.PAY_SUCCESS"); // 2. 携带数据(键值对形式) intent.putExtra("orderId", "123456"); intent.putExtra("amount", 99.0); // 3. 发送无序广播 sendBroadcast(intent); // 发送时可以带上权限字符串,只有拥有该权限的接收者才能收到。 sendBroadcast(intent, "com.example.PERMISSION"); // 发送本地无序广播(仅应用内可见) LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

发送有序广播

Intent intent = new Intent("com.example.app.SMS_RECEIVED"); intent.putExtra("smsContent", "【验证码】123456"); // 发送有序广播,第二个参数是权限(若为null,所有应用均可接收) // 优先级高的接收者可截断广播 sendOrderedBroadcast(intent, null); // 有序广播的截断与数据修改示例(在接收者的onReceive中) @Override public void onReceive(Context context, Intent intent) { if ("com.example.app.SMS_RECEIVED".equals(intent.getAction())) { // 1. 修改广播数据 setResultData("【拦截后】验证码已屏蔽"); // 2. 截断广播,后续接收者无法收到 abortBroadcast(); } }

四、实践一下:监听系统网络变化

1. 声明权限

<!-- 访问网络状态权限 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

2. 定义广播接收者

public class NetworkChangeReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { // 适配API 23+的网络状态获取方式 ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Network network = cm.getActiveNetwork(); NetworkCapabilities capabilities = cm.getNetworkCapabilities(network); if (capabilities != null) { if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { sendNetworkEvent(context, "WiFi网络"); } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { sendNetworkEvent(context, "移动数据网络"); } else { sendNetworkEvent(context, "无网络连接"); } } else { sendNetworkEvent(context, "无网络连接"); } } else { // 兼容低版本 NetworkInfo info = cm.getActiveNetworkInfo(); if (info != null && info.isConnected()) { if (info.getType() == ConnectivityManager.TYPE_WIFI) { sendNetworkEvent(context, "WiFi网络"); } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) { sendNetworkEvent(context, "移动数据网络"); } } else { sendNetworkEvent(context, "无网络连接"); } } } // 发送事件到Activity(可通过接口或LiveData优化) private void sendNetworkEvent(Context context, String state) { if (context instanceof MainActivity) { ((MainActivity) context).onNetworkStateChanged(state); } } }

3. 动态注册与注销

public class MainActivity extends AppCompatActivity { private NetworkChangeReceiver networkReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 注册网络变化广播 networkReceiver = new NetworkChangeReceiver(); IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); registerReceiver(networkReceiver, intentFilter); } // 接收网络状态变化事件,更新UI public void onNetworkStateChanged(String state) { TextView tvNetwork = findViewById(R.id.tv_network); tvNetwork.setText("当前网络:" + state); } @Override protected void onDestroy() { super.onDestroy(); // 注销广播 unregisterReceiver(networkReceiver); } }

结语

广播(Broadcast)作为 Android 四大组件之一,虽然概念诞生已久,但它从未过时。从最早的肆意发送,到如今 Android 8.0 的隐式限制、Android 14 的导出标志强制化,广播机制的每一次演变都折射出 Android 系统对性能与安全的极致追求。

对于开发者而言,掌握广播不仅仅是学会写onReceive,更重要的是理解其背后的设计模式与系统边界。在实际开发中,我们应遵循“最小权限原则”,尽量使用动态注册,善用SharedFlow等现代技术替代本地广播,并时刻关注系统版本的迭代差异。

希望这篇文章能帮你构建起完整的广播知识体系。组件通信的方式有千万种,愿你能根据场景,选择最优雅的那一种。Happy Coding!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询