02_BroadcastReceiver注册方式与生命周期_修订版
02 BroadcastReceiver 注册方式与生命周期
基于原 PDF 修订、联网校对并补充缺失内容
1. BroadcastReceiver 的核心职责
BroadcastReceiver 是接收广播的组件。真正需要重写的方法是 onReceive(Context context, Intent intent),不是 onReceiver。原 PDF 中多处把 onReceive 写成 onReceiver,需要修正。
class BootCompleteReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (Intent.ACTION_BOOT_COMPLETED == intent.action) {
// 不要在这里做长耗时任务,尽快转交给 WorkManager/JobScheduler
}
}
}
2. 两种注册方式
| 方式 | 注册位置 | 能否在应用未运行时被唤起 | 适用场景 | 注意点 |
|---|---|---|---|---|
| Manifest-declared receiver | AndroidManifest.xml 的 |
可以,但受系统版本和广播类型限制 | 开机完成、包变更等需要系统唤起的事件 | Android 8.0 起多数隐式广播不能静态注册;Android 12 起带 intent-filter 的组件必须显式 android:exported。 |
| Context-registered receiver | 代码中 registerReceiver() | 通常依赖注册该 receiver 的 context 是否仍有效 | 页面可见期间、服务运行期间、短周期监听 | 必须 unregister;Android 14 target 34 起一般要声明 RECEIVER_EXPORTED/NOT_EXPORTED。 |
3. 静态注册示例:开机广播
开机广播属于典型 manifest receiver 场景,但必须声明 RECEIVE_BOOT_COMPLETED 权限,并注意设备加密、Direct Boot 以及厂商省电策略的影响。
<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<application ...>
<receiver
android:name=".receiver.BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
如果 receiver 只接收本应用内部显式广播,通常应设为 android:exported=“false”。如果要接收系统或其他应用发来的广播,需要按场景设为 true,并结合权限和数据校验。
4. 动态注册示例:页面可见期间监听
动态注册建议选择最小生命周期范围。页面只在前台需要监听时,可在 onStart/onStop 或 onResume/onPause 成对注册与注销。
class MainActivity : AppCompatActivity() {
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// 处理广播,尽快返回
}
}
override fun onStart() {
super.onStart()
val filter = IntentFilter("com.example.app.ACTION_UPDATE")
ContextCompat.registerReceiver(
this,
receiver,
filter,
ContextCompat.RECEIVER_NOT_EXPORTED
)
}
override fun onStop() {
unregisterReceiver(receiver)
super.onStop()
}
}
- onResume/onPause:只在 Activity 可交互时接收。
- onStart/onStop:只在 Activity 可见时接收。
- onCreate/onDestroy:Activity 创建到销毁期间接收,但更容易因忘记注销导致泄漏。
- Application context:适合跨 Activity 生命周期监听,但要自己管理注销时机。
5. Android 14 动态 receiver 导出标记
当应用 target Android 14/API 34 或更高,使用 context-registered receiver 时,一般要指定 RECEIVER_EXPORTED 或 RECEIVER_NOT_EXPORTED。仅接收系统广播的特殊情况不需要指定这个 flag。
| flag | 含义 | 何时使用 |
|---|---|---|
| RECEIVER_NOT_EXPORTED | 不对其他应用可见 | 只接收本应用发送的广播,安全默认值。 |
| RECEIVER_EXPORTED | 允许接收其他应用/部分特权系统应用广播 | 接收跨应用广播或部分非 system UID 的系统组件广播时使用。 |
6. onReceive 的时间限制与异步处理
onReceive 通常运行在主线程,必须快速返回。官方 API 说明中提到,BroadcastReceiver 一般只有约 10 秒处理时间,超时可能触发 ANR。
- 短任务:直接在 onReceive 中做最少量处理。
- 需要异步但很短:使用 goAsync(),把 PendingResult 传给后台线程,完成后调用 finish()。
- 可靠后台任务:使用 WorkManager/JobScheduler,不要在 receiver 里启动长线程后就返回。
- 不要从 receiver 直接启动 Activity,用户体验差;用通知引导用户更合理。
override fun onReceive(context: Context, intent: Intent) {
val pendingResult = goAsync()
CoroutineScope(Dispatchers.IO).launch {
try {
// 短时间后台处理
} finally {
pendingResult.finish()
}
}
}
7. 原 PDF 动态注册代码修订点
| 原写法/问题 | 修正 |
|---|---|
| super.Oncreata(savedInstanceState) | super.onCreate(savedInstanceState) |
| @Overrid | @Override |
| public void onReceiver(…) | public void onReceive(…) |
| sendOrderBroadcast | sendOrderedBroadcast |
| CONNECTIVITY_CHANGE 静态注册或旧 NetworkInfo 写法 | 动态注册或使用 ConnectivityManager.NetworkCallback/NetworkCapabilities。 |
参考资料
- Android Developers - Broadcasts overview: https://developer.android.com/develop/background-work/background-tasks/broadcasts
- Android Developers - Implicit broadcast exceptions: https://developer.android.com/develop/background-work/background-tasks/broadcasts/broadcast-exceptions
- Android Developers - BroadcastReceiver API reference: https://developer.android.com/reference/android/content/BroadcastReceiver
- Android Developers - LocalBroadcastManager release notes: https://developer.android.com/jetpack/androidx/releases/localbroadcastmanager
- Android Developers - Android 14 behavior changes: https://developer.android.com/about/versions/14/behavior-changes-14
- Android Developers - Android 12 behavior changes: https://developer.android.com/about/versions/12/behavior-changes-12
- Android Developers - ConnectivityManager API reference: https://developer.android.com/reference/android/net/ConnectivityManager
- Android Developers - Sticky broadcasts risk: https://developer.android.com/privacy-and-security/risks/sticky-broadcast