一、 BroadcastReceiver 核心机制与考点

在面试中,面试官首先会询问你对BroadcastReceiver的基本理解。你需要清晰地区分静态注册与动态注册的区别,并深入理解其生命周期。

① 静态注册 (Static Registration)

在 AndroidManifest.xml 中声明。即使应用未启动,也能接收广播。适用于需要长期监听系统事件(如开机完成、网络变化)的场景。

  • 优点:应用未运行也可接收。
  • 缺点:启动慢,占用资源,高版本限制严格。

② 动态注册 (Dynamic Registration)

通过 registerReceiver() 代码注册。随Activity/Service生命周期变化,应用退出后自动失效。

  • 优点:灵活,可注销,性能开销小。
  • 缺点:应用未运行无法接收,需防止内存泄漏。

③ 生命周期管理

BroadcastReceiver 是短生命周期的组件。当广播到来时,系统调用 onReceive(),执行完毕后销毁。若在 onReceive() 中执行耗时操作,会导致ANR。

有序广播与普通广播的区别

这是面试中的经典对比题。普通广播(Normal Broadcast)是完全异步的,所有接收者几乎同时收到,无法截断。有序广播(Ordered Broadcast)则按照优先级顺序执行,高优先级的接收者可以先处理广播,甚至通过 abortBroadcast() 截断传播,或通过 setResult() 传递数据给下一个接收者。

二、 安全漏洞与导出问题

随着Android安全规范的收紧,BroadcastReceiver的安全性成为面试的高频考点。特别是“导出漏洞”和“权限控制”。

什么是导出漏洞?

如果 BroadcastReceiver 在 AndroidManifest.xml 中注册时未设置 android:exported="false"(Android 12+ 强制要求),或者显式设置为 true,则其他应用可以发送广播给该组件。

风险:攻击者可以发送恶意广播,触发你的 onReceive(),可能导致逻辑混乱、数据泄露甚至远程代码执行(如果处理不当)。

解决方案:

  • 对于不对外开放的内部广播,务必设置 android:exported="false"。
  • 对于需要对外开放的,必须使用 android:permission 进行权限校验。

如何保护广播?

使用自定义权限是保护 BroadcastReceiver 的重要手段。

<permission android:name="com.example.MY_BROADCAST_PERMISSION"
            android:protectionLevel="signature" />
<receiver android:name=".MyReceiver"
          android:exported="true"
          android:permission="com.example.MY_BROADCAST_PERMISSION">
    <intent-filter>
        <action android:name="com.example.CUSTOM_ACTION" />
    </intent-filter>
</receiver>

这样,只有拥有 com.example.MY_BROADCAST_PERMISSION 权限的应用才能发送或接收该广播。

常见的内存泄漏场景

在动态注册时,如果忘记在 onDestroy() 中调用 unregisterReceiver(),会导致 BroadcastReceiver 实例持有 Activity 引用,从而引发内存泄漏。

最佳实践:

  • 在 onCreate() 注册,在 onDestroy() 注销。
  • 使用局部内部类或静态内部类 + WeakReference 避免持有外部类引用。
  • 考虑使用 LocalBroadcastManager(已废弃,推荐用 LiveData 或 Flow 替代)或 ContextCompat.registerReceiver。

三、 Android 12 (API 31+) 及后续版本适配

从 Android 12 开始,Google 对隐式广播进行了严格限制。这是面试中区分初级与高级开发者的关键知识点。

Android 8.0 (API 26)

后台限制

禁止在 AndroidManifest.xml 中注册大部分隐式广播。静态注册的 BroadcastReceiver 只能接收特定的系统广播(如开机、锁屏等)。

Android 12 (API 31)

隐式广播移除

移除了超过30个隐式广播。应用若需监听这些广播,必须改为显式广播或使用其他替代方案(如 JobScheduler, WorkManager, ConnectivityManager.NetworkCallback)。

Android 13 (API 33)

精确闹钟与蓝牙扫描

进一步限制了后台权限,BroadcastReceiver 若涉及敏感权限,需在清单中声明用途。

替代方案建议

当隐式广播不可用时,推荐使用以下替代方案:

  • 网络状态: 使用 ConnectivityManager.NetworkCallback。
  • 电量变化: 使用 BatteryManager 的静态注册或 LiveData。
  • 应用间通信: 使用 ContentProvider 或 IPC 机制。

四、 面试官最爱问的10个高频真题

以下整理了网络上求职者反馈频率最高的问题,并提供了深度解答思路。

序号 问题描述 核心考点 简答要点
1 静态注册和动态注册有什么区别? 生命周期、注册方式 静态在Manifest,应用未启动也可收;动态在代码,随组件生命周期。
2 有序广播是如何实现的? 广播类型、优先级 通过 android:priority 排序,高优先者先执行,可截断或修改结果。
3 onReceive 中能执行耗时操作吗? ANR、线程模型 不能。会阻塞主线程导致ANR。应启动 Service 或使用线程池。
4 什么是粘性广播?现在还能用吗? 废弃API、安全 已废弃。Android 5.0+ 禁止使用 sendStickyBroadcast,因为存在安全风险。
5 Android 12 对广播做了什么限制? 版本适配、隐式广播 移除了大量隐式广播,强制要求显式广播或特定权限。
6 如何防止广播被恶意拦截? 安全、权限 设置 android:exported="false" 或使用自定义 permission。
7 LocalBroadcastManager 是什么?为什么被废弃? 本地广播、架构演进 用于应用内广播,更安全高效。现被 LiveData/Flow 替代。
8 广播发送者和接收者可以在不同进程吗? 跨进程通信、Binder 可以。广播基于 Binder 机制,天然支持跨进程。
9 如何优化大量接收者的广播性能? 性能优化、异步 使用普通广播(异步),减少优先级排序开销,避免在 onReceive 做重操作。
10 广播的优先级最大是多少? 细节知识 最大 1000,最小 -1000。数字越大优先级越高。

总结

掌握 BroadcastReceiver 不仅是应对面试的必要条件,更是理解 Android 系统通信机制的基础。随着 Android 版本的迭代,其使用场景正在逐渐被更现代化的架构组件所补充或替代,但核心原理依然重要。希望本篇攻略能助你在面试中脱颖而出。