Android开发-应用广播
一、广播的核心概念
1. 什么是广播?
- 广播(Broadcast):一条携带特定动作(Action)的
Intent
消息。 - 发送者(Sender):通过
sendBroadcast()
、sendOrderedBroadcast()
等方法发送广播。 - 接收者(Receiver):继承
BroadcastReceiver
的组件,用于接收并处理广播。
2. 广播的类型
类型 | 描述 | 示例 |
---|---|---|
标准广播(Normal Broadcast) | 异步、无序发送,所有接收者几乎同时收到 | sendBroadcast() |
有序广播(Ordered Broadcast) | 同步、按优先级顺序发送,可被拦截 | sendOrderedBroadcast() |
粘性广播(Sticky Broadcast) | 广播发送后会“粘住”,新注册的接收者可立即收到 | sendStickyBroadcast() (已废弃) |
本地广播(Local Broadcast) | 仅在应用内部发送和接收,更安全高效 | LocalBroadcastManager (已废弃) |
二、广播接收者(BroadcastReceiver)
1. 定义 BroadcastReceiver
public class MyReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();switch (action) {case Intent.ACTION_BOOT_COMPLETED:Log.d("MyReceiver", "设备开机完成!");// 可在此启动后台服务(需用户授权)break;case Intent.ACTION_BATTERY_LOW:Log.d("MyReceiver", "电池电量低!");Toast.makeText(context, "电量不足,请及时充电", Toast.LENGTH_LONG).show();break;case "com.example.CUSTOM_ACTION":String data = intent.getStringExtra("data");Log.d("MyReceiver", "收到自定义广播:" + data);break;}}
}
⚠️ 注意:
onReceive()
方法在主线程执行,不能进行耗时操作(如网络请求、数据库读写)。如需后台任务,应启动Service
。
三、注册广播接收者
方式 1:静态注册(清单文件注册)
在 AndroidManifest.xml
中声明,即使应用未运行也能接收广播。
<receiver android:name=".MyReceiver" android:enabled="true" android:exported="false"><intent-filter android:priority="1000"><action android:name="android.intent.action.BOOT_COMPLETED" /><action android:name="android.intent.action.BATTERY_LOW" /><!-- 自定义广播 --><action android:name="com.example.CUSTOM_ACTION" /></intent-filter>
</receiver>
🔐 权限说明
<!-- 接收开机广播需要权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /><!-- 接收网络状态变化 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
✅ 优点:应用未启动也能接收系统广播。
❌ 缺点:可能被滥用,影响系统性能。
方式 2:动态注册(代码注册)
在 Activity
或 Service
中注册,生命周期与组件绑定。
public class MainActivity extends AppCompatActivity {private MyReceiver receiver;private IntentFilter filter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 创建过滤器filter = new IntentFilter();filter.addAction(Intent.ACTION_BATTERY_LOW);filter.addAction("com.example.CUSTOM_ACTION");// 创建接收者receiver = new MyReceiver();// 注册registerReceiver(receiver, filter);}@Overrideprotected void onDestroy() {super.onDestroy();// 必须反注册,防止内存泄漏!if (receiver != null) {unregisterReceiver(receiver);}}// 发送自定义广播public void sendCustomBroadcast(View view) {Intent intent = new Intent("com.example.CUSTOM_ACTION");intent.putExtra("data", "Hello from Activity!");sendBroadcast(intent);}
}
✅ 优点:灵活,可动态控制生命周期。
❌ 缺点:组件销毁后无法接收广播。
四、系统广播 vs 自定义广播
1. 常见系统广播
广播 Action | 说明 | 权限 |
---|---|---|
ACTION_BOOT_COMPLETED | 开机完成 | RECEIVE_BOOT_COMPLETED |
ACTION_BATTERY_LOW | 电池电量低 | 无 |
ACTION_POWER_CONNECTED | 充电连接 | 无 |
ACTION_TIMEZONE_CHANGED | 时区变更 | 无 |
CONNECTIVITY_ACTION | 网络连接状态变化 | ACCESS_NETWORK_STATE |
ACTION_SHUTDOWN | 设备关机 | SHUTDOWN |
📢 注意:部分系统广播(如
BOOT_COMPLETED
)在 Android 8.0+ 受到限制,应用必须在前台运行或用户明确授权才能接收。
2. 自定义广播
应用内部或跨应用通信。
// 发送
Intent intent = new Intent("com.yourcompany.YOUR_ACTION");
intent.putExtra("message", "Data from sender");
sendBroadcast(intent);// 接收(需在清单或代码中注册该 action)
🔐 安全建议:
- 使用应用专属权限防止第三方应用接收。
- 避免在广播中传递敏感信息。
五、Android 8.0+ 的广播限制
从 Android 8.0(API 26) 开始,Google 为了优化电池续航和系统性能,对隐式广播(Implicit Broadcasts)进行了严格限制。
1. 主要限制
- ❌ 禁止在清单中静态注册大部分隐式广播(即非应用专属的 action)。
- ✅ 仅允许在代码中动态注册。
- ✅ 少数例外(如
BOOT_COMPLETED
、TIMEZONE_CHANGED
)仍可在清单注册。
2. 如何适配?
- 将原本静态注册的广播改为动态注册,并在合适的生命周期(如
onStart()
/onStop()
)中注册/反注册。 - 考虑使用 JobScheduler 或 WorkManager 替代长时间运行的广播任务。
六、现代替代方案
由于广播的限制和性能开销,Google 推荐使用更高效的通信方式:
1. 本地事件总线(推荐)
使用 LiveData
或 Flow
实现组件间通信。
// 使用 ViewModel + LiveData
public class SharedViewModel extends ViewModel {private MutableLiveData<String> message = new MutableLiveData<>();public LiveData<String> getMessage() { return message; }public void sendMessage(String msg) {message.setValue(msg);}
}
2. WorkManager
对于需要在特定条件下执行的后台任务(如网络可用时上传数据),使用 WorkManager
。
OneTimeWorkRequest work = new OneTimeWorkRequest.Builder(UploadWorker.class).setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()).build();WorkManager.getInstance(context).enqueue(work);
3. PendingIntent + AlarmManager
对于定时任务,使用 AlarmManager
设置 PendingIntent
。
七、最佳实践与避坑指南
- 务必在
onDestroy()
或onStop()
中反注册动态广播,防止内存泄漏。 - 避免在
onReceive()
中执行耗时操作,应启动Service
或使用WorkManager
。 - 优先使用显式广播(指定包名)或应用内通信。
- 为自定义广播添加权限,提高安全性。
- Android 12+:部分广播(如
PACKAGE_ADDED
)需要特殊权限或用户授权。
八、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!