Android随笔-BroadcastReceiver

📅 2026/7/16 18:25:32
Android随笔-BroadcastReceiver
Android Broadcast 详解一、BroadcastReceiver是什么BroadcastReceiver是 Android 四大组件之一Activity、Service、BroadcastReceiver、ContentProvider本质上是一种发布-订阅模式的通信机制发送方通过sendBroadcast()发送 Intent接收方通过BroadcastReceiver的onReceive()接收并处理广播可以实现应用内部组件通信跨应用通信系统广播、自定义广播系统事件监听开机、网络变化、电量变化等二、广播的类型与区别1. 按注册方式分类类型注册方式生命周期特点静态广播AndroidManifest.xml中receiver标签应用未运行也能接收系统级事件、开机启动动态广播代码中registerReceiver()随注册组件生命周期灵活控制、性能更好2. 按发送方式分类类型发送方法特点安全性普通广播sendBroadcast()异步、无序、同时发送给所有接收者低可被任意应用接收有序广播sendOrderedBroadcast()同步、按优先级顺序传递可拦截/修改中等本地广播LocalBroadcastManager.sendBroadcast()仅应用内部通信效率更高高已废弃3. 按发送范围分类类型说明使用场景系统广播Android 系统发送如开机、网络变化监听系统状态变化自定义广播应用自己发送应用内部/跨应用通信三、核心原理发送与接收流程发送方 ↓ Context.sendBroadcast(Intent) ↓ AMS (ActivityManagerService) ↓ 遍历所有已注册的 BroadcastReceiver ↓ ┌─────────────────┐ │ 静态广播 │ → 通过 PackageManager 解析 Manifest │ 动态广播 │ → 通过 AMS 维护的 Receiver 列表 └─────────────────┘ ↓ 匹配 IntentFilteraction、category、data 等 ↓ 创建 BroadcastReceiver 实例 ↓ 调用 onReceive(Context, Intent) [主线程] ↓ onReceive 执行完毕 → 销毁 Receiver 实例关键原理点Receiver 是临时实例每次广播到达时系统会创建新的BroadcastReceiver实例执行完onReceive()后立即销毁onReceive 在主线程执行耗时操作会导致 ANR10 秒超时AMS 统一管理所有广播路由都经过ActivityManagerService四、使用示例1. 静态广播Manifest 注册!-- AndroidManifest.xml --receiverandroid:name.BootReceiverandroid:exportedtrue!-- exportedtrue 允许跨应用接收 --intent-filteractionandroid:nameandroid.intent.action.BOOT_COMPLETED//intent-filter/receiver!-- 自定义广播 --receiverandroid:name.MyReceiverandroid:exportedfalse!-- 仅应用内部 --intent-filteractionandroid:namecom.example.ACTION_CUSTOM//intent-filter/receiver// 接收器实现publicclassBootReceiverextendsBroadcastReceiver{OverridepublicvoidonReceive(Contextcontext,Intentintent){if(Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())){// 开机启动逻辑IntentserviceIntentnewIntent(context,MyService.class);context.startService(serviceIntent);}}}2. 动态广播代码注册publicclassMainActivityextendsAppCompatActivity{privateMyReceiverreceiver;privateIntentFilterfilter;OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);receivernewMyReceiver();filternewIntentFilter();filter.addAction(com.example.ACTION_CUSTOM);filter.addAction(Intent.ACTION_SCREEN_ON);// 注册registerReceiver(receiver,filter);}OverrideprotectedvoidonDestroy(){super.onDestroy();// 必须注销否则内存泄漏unregisterReceiver(receiver);}// 发送广播publicvoidsendCustomBroadcast(){IntentintentnewIntent(com.example.ACTION_CUSTOM);intent.putExtra(data,hello);sendBroadcast(intent);}}publicclassMyReceiverextendsBroadcastReceiver{OverridepublicvoidonReceive(Contextcontext,Intentintent){Stringactionintent.getAction();if(com.example.ACTION_CUSTOM.equals(action)){Stringdataintent.getStringExtra(data);Log.d(MyReceiver,收到: data);}}}3. 有序广播// 发送有序广播publicvoidsendOrderedBroadcast(){IntentintentnewIntent(com.example.ACTION_ORDERED);sendOrderedBroadcast(intent,null);// 第二个参数是权限}!-- 接收器设置优先级 --receiverandroid:name.HighPriorityReceiverintent-filterandroid:priority100!-- 优先级越高越先收到 --actionandroid:namecom.example.ACTION_ORDERED//intent-filter/receiverreceiverandroid:name.LowPriorityReceiverintent-filterandroid:priority1actionandroid:namecom.example.ACTION_ORDERED//intent-filter/receiver// 高优先级接收器可以拦截或修改广播publicclassHighPriorityReceiverextendsBroadcastReceiver{OverridepublicvoidonReceive(Contextcontext,Intentintent){// 修改结果数据setResultData(modified_data);// 拦截广播不再传递给低优先级接收器abortBroadcast();}}4. 本地广播已废弃了解即可// LocalBroadcastManager 已废弃建议使用 LiveData / Flow 替代// 或直接使用 exportedfalse 的广播五、系统常用广播广播 Action说明权限要求ACTION_BOOT_COMPLETED开机完成RECEIVE_BOOT_COMPLETEDACTION_SCREEN_ON/OFF屏幕亮/灭无ACTION_BATTERY_CHANGED电量变化无粘性广播ACTION_CONNECTIVITY_CHANGE网络变化ACCESS_NETWORK_STATEACTION_PACKAGE_ADDED/REMOVED应用安装/卸载无ACTION_TIME_TICK每分钟触发无六、注意事项1. ANR 风险最重要// ❌ 错误onReceive 中做耗时操作OverridepublicvoidonReceive(Contextcontext,Intentintent){// 超过 10 秒就会 ANRdownloadLargeFile();}// ✅ 正确使用 goAsync() 或启动 ServiceOverridepublicvoidonReceive(Contextcontext,Intentintent){finalPendingResultpendingResultgoAsync();newThread(()-{try{downloadLargeFile();}finally{pendingResult.finish();// 必须调用}}).start();}// ✅ 更推荐启动 Service 或 WorkManagerOverridepublicvoidonReceive(Contextcontext,Intentintent){IntentserviceIntentnewIntent(context,MyService.class);context.startService(serviceIntent);}2. 内存泄漏// ❌ 错误匿名内部类持有 Activity 引用publicclassMainActivityextendsAppCompatActivity{OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);// 匿名内部类隐式持有 MainActivity 引用registerReceiver(newBroadcastReceiver(){OverridepublicvoidonReceive(Contextcontext,Intentintent){// 如果 Activity 已销毁但 Receiver 未注销泄漏}},newIntentFilter(ACTION));}}// ✅ 正确使用成员变量 成对注册/注销publicclassMainActivityextendsAppCompatActivity{privateBroadcastReceiverreceiver;OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);receivernewMyReceiver();registerReceiver(receiver,newIntentFilter(ACTION));}OverrideprotectedvoidonDestroy(){super.onDestroy();unregisterReceiver(receiver);// 必须注销}}3. Android 8.0 后台限制// ⚠️ Android 8.0 (API 26) 开始大部分隐式广播无法通过静态注册接收// 以下广播仍支持静态注册// - 开机完成 (BOOT_COMPLETED)// - 应用安装/卸载 (PACKAGE_ADDED/REMOVED)// - 时区变化 (TIMEZONE_CHANGED)// - 语言变化 (LOCALE_CHANGED)// ❌ 以下广播不再支持静态注册// - 网络变化 (CONNECTIVITY_CHANGE)// - 屏幕亮灭 (SCREEN_ON/OFF)// - 电量变化 (BATTERY_CHANGED)// ✅ 解决方案改用动态注册OverrideprotectedvoidonCreate(BundlesavedInstanceState){super.onCreate(savedInstanceState);registerReceiver(networkReceiver,newIntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));}4. 安全性// ❌ 错误exportedtrue 且无权限控制任意应用可发送/接收receiver android:name.MyReceiverandroid:exportedtrueintent-filteraction android:namecom.example.ACTION//intent-filter/receiver!-- ✅ 正确自定义权限控制 --!-- 1. 定义权限发送方和接收方都要声明 --permissionandroid:namecom.example.permission.RECEIVE_BROADCASTandroid:protectionLevelsignature/!-- 2. 发送方声明权限 --uses-permissionandroid:namecom.example.permission.RECEIVE_BROADCAST/!-- 3. 接收方要求权限 --receiverandroid:name.MyReceiverandroid:permissioncom.example.permission.RECEIVE_BROADCASTandroid:exportedtrueintent-filteractionandroid:namecom.example.ACTION//intent-filter/receiver// 4. 发送时指定权限sendBroadcast(intent,com.example.permission.RECEIVE_BROADCAST);!-- ✅ 更推荐使用 exportedfalse 限制应用内部 --receiverandroid:name.InternalReceiverandroid:exportedfalseintent-filteractionandroid:namecom.example.ACTION_INTERNAL//intent-filter/receiver5. 跨进程通信// 跨应用广播需要 exportedtrue// 或使用显式 Intent 指定目标包名IntentintentnewIntent();intent.setAction(com.example.ACTION);intent.setPackage(com.target.app);// 指定接收方包名sendBroadcast(intent);6. 粘性广播已废弃// ⚠️ sendStickyBroadcast() 已废弃不要使用// 替代方案使用 LiveData、SharedPreferences 或 ContentProvider7. 本地广播替代方案// LocalBroadcastManager 已废弃推荐使用// 1. LiveData / MutableLiveData应用内通信// 2. Kotlin Flow / SharedFlow// 3. EventBus第三方库// 4. RxBusRxJava// ✅ 示例使用 LiveDataclassEventBus{privateval _eventsMutableLiveDataEvent()val events:LiveDataEvent_events funpost(event:Event){_events.valueevent}}七、总结问题答案BroadcastReceiver是什么Android 发布-订阅模式的组件间通信机制核心原理通过 AMS 路由匹配 IntentFilter在主线程回调 onReceive静态 vs 动态静态应用未运行也能接收动态灵活、性能更好、需手动注销普通 vs 有序普通异步无序有序同步按优先级可拦截主要风险ANR10秒限制、内存泄漏、Android 8.0 后台限制现代替代方案应用内通信用 LiveData/Flow跨组件用 WorkManager/Service一句话总结BroadcastReceiver是 Android 的全局事件总线适合系统事件监听和跨应用通信应用内部通信优先使用 LiveData/Flow避免广播带来的性能和安全问题。