1. Android广播机制基础解析
广播(Broadcast)是Android系统中应用间通信的核心机制之一,它采用发布-订阅模式实现跨进程消息传递。当系统或应用发生特定事件时(如网络状态变化、电池电量不足等),会发送对应的广播消息,所有注册监听该广播的接收器都会收到通知。
1.1 广播的核心组件
广播机制主要涉及三个核心类:
- Intent :封装广播消息的载体,包含action字符串标识事件类型,以及可选的附加数据
- IntentFilter :用于声明接收器感兴趣的广播类型
- BroadcastReceiver :接收并处理广播的组件
典型广播工作流程如下:
- 发送方创建包含特定action的Intent
- 通过sendBroadcast()等方法发送广播
- 系统匹配已注册的接收器
- 调用匹配接收器的onReceive()方法
1.2 广播的类型对比
Android支持两种主要广播类型:
| 类型 | 发送方法 | 特点 | 适用场景 |
|---|---|---|---|
| 普通广播 | sendBroadcast() | 异步发送,所有接收器同时接收 | 常规事件通知 |
| 有序广播 | sendOrderedBroadcast() | 顺序发送,可中断传递 | 需要处理顺序或结果的场景 |
提示:Android 8.0后对隐式广播做了严格限制,建议优先使用显式广播或本地广播
2. 广播接收器的实现方式
2.1 动态注册(上下文注册)
动态注册的生命周期与注册上下文绑定,通常用在Activity或Service中:
class MainActivity : AppCompatActivity() {
private lateinit var receiver: MyReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
receiver = MyReceiver()
val filter = IntentFilter().apply {
addAction("com.example.MY_ACTION")
}
registerReceiver(receiver, filter)
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(receiver) // 必须手动注销
}
}
关键注意事项:
- 必须在组件销毁时调用unregisterReceiver()
- 避免在onReceive()中执行耗时操作(超过10秒可能导致ANR)
- Android 8.0+限制后台接收器必须使用动态注册
2.2 静态注册(清单声明)
在AndroidManifest.xml中声明:
<receiver
android:name=".MyReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
版本兼容性要点:
- Android 8.0+:禁止大多数隐式广播的静态注册
- Android 7.0+:CONNECTIVITY_ACTION必须动态注册
- 建议同时设置android:exported属性明确导出范围
3. 本地广播的优化实现
全局广播存在安全性问题和性能开销,LocalBroadcastManager是更好的选择:
// 发送本地广播
val intent = Intent("com.example.LOCAL_ACTION")
intent.putExtra("key", "value")
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
// 接收本地广播
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// 处理广播
}
}
LocalBroadcastManager.getInstance(this)
.registerReceiver(receiver, IntentFilter("com.example.LOCAL_ACTION"))
本地广播优势:
- 只在应用内部传递,更安全
- 不需要进程间通信,效率更高
- 不受系统广播限制影响
4. 广播实战:监听网络状态变化
以下是完整的网络状态监听实现:
class NetworkReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val connectivityManager = context.getSystemService(
Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = connectivityManager.activeNetworkInfo
when {
networkInfo == null -> showToast(context, "无网络连接")
!networkInfo.isConnected -> showToast(context, "网络断开")
networkInfo.type == ConnectivityManager.TYPE_WIFI ->
showToast(context, "已连接WIFI")
networkInfo.type == ConnectivityManager.TYPE_MOBILE ->
showToast(context, "使用移动数据")
}
}
private fun showToast(context: Context, message: String) {
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
}
}
// 在Activity中注册
val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
registerReceiver(NetworkReceiver(), filter)
需要声明的权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
5. 广播使用的高级技巧
5.1 处理有序广播
有序广播允许设置优先级和传递结果:
// 发送有序广播
sendOrderedBroadcast(
Intent("com.example.ORDERED_ACTION"),
null, // 权限
resultReceiver, // 最终接收器
null, // Handler
Activity.RESULT_OK,
null, // initialData
null // initialExtras
)
// 接收器中可操作广播
override fun onReceive(context: Context, intent: Intent) {
val code = resultCode
val data = resultData
val extras = getResultExtras(true)
// 修改结果
setResult(Activity.RESULT_CANCELED, "修改的数据", extras)
// 中止广播
abortBroadcast()
}
5.2 使用PendingResult处理耗时操作
解决onReceive()不能长时间运行的限制:
override fun onReceive(context: Context, intent: Intent) {
val pendingResult = goAsync()
thread {
// 执行耗时操作
Thread.sleep(5000)
pendingResult.finish()
}
}
5.3 广播权限控制
通过权限保护广播安全:
// 发送带权限的广播
sendBroadcast(intent, "com.example.MY_PERMISSION")
// 接收带权限的广播
<receiver
android:name=".ProtectedReceiver"
android:permission="com.example.MY_PERMISSION">
...
</receiver>
6. 常见问题排查
6.1 接收不到广播的可能原因
- IntentFilter不匹配 :检查action是否完全一致
- 权限问题 :发送/接收方是否声明了所需权限
- 版本限制 :Android 8.0+对隐式广播的限制
- 进程状态 :静态注册时应用是否已启动
- LocalBroadcastManager未正确使用 :确保发送接收使用同一实例
6.2 性能优化建议
- 避免频繁发送高频率广播
- 对不需要跨应用的广播使用LocalBroadcastManager
- 及时注销不再需要的接收器
- 将多个广播合并为单个复合广播
- 对耗时操作使用goAsync()或JobScheduler
6.3 广播与ViewModel结合的最佳实践
class MyViewModel : ViewModel() {
private val _events = MutableLiveData<String>()
val events: LiveData<String> = _events
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
_events.value = intent.getStringExtra("data")
}
}
fun registerReceiver(context: Context) {
val filter = IntentFilter("com.example.ACTION")
context.registerReceiver(receiver, filter)
}
fun unregisterReceiver(context: Context) {
context.unregisterReceiver(receiver)
}
override fun onCleared() {
// 清理资源
}
}
这种模式解决了Activity重建时的接收器管理问题,同时保持了良好的架构分层。

4315

被折叠的 条评论
为什么被折叠?



