Android 通用功能封装7——广播管理

http://rainmonth.github.io/posts/A210208.html

简介

先了解一下广播的概念,然后从广播的类型、使用注意事项等几方面对广播做了简单的介绍,最后在对广播的使用做简单的封装;


1. 广播核心概念

  • 定义:Android 广播(Broadcast)是一种 跨组件/跨进程通信机制,基于观察者模式实现,允许应用或系统发送全局消息。
  • 典型场景
    • 系统事件(如网络变化、电量不足、屏幕亮灭)
    • 应用内组件通信(如 Activity 通知 Service 更新数据)
    • 跨应用通信(需权限控制)

2. 广播类型

类型 特点 示例场景
普通广播 异步发送,所有接收器无序执行 自定义事件通知(无需处理顺序)
有序广播 同步发送,接收器按优先级顺序处理,可中断传递 动态调整功能链(如拦截短信广播)
本地广播 仅限应用内部通信,通过 LocalBroadcastManager 实现,安全高效 应用内组件间通信

3. 广播注册方式

动态注册(推荐)

  • 生命周期绑定:在代码中通过 registerReceiver() 注册,需在组件销毁时调用 unregisterReceiver()

  • 灵活性高:适合监听临时事件。

    1
    2
    3
    // 示例:动态注册网络状态监听
    IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
    registerReceiver(networkReceiver, filter);

静态注册(谨慎使用)

  • AndroidManifest.xml 声明:应用未运行时也能接收广播(如开机启动)。

  • 限制:Android 8.0+ 禁止大部分隐式广播静态注册(防止滥用耗电)。

    1
    2
    3
    4
    5
    <receiver android:name=".MyReceiver">
    <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED"/>
    </intent-filter>
    </receiver>

4. 发送广播

发送普通广播

1
2
3
Intent intent = new Intent("com.example.MY_ACTION");
intent.putExtra("data", "Hello from Broadcast!");
sendBroadcast(intent);

发送有序广播

1
2
Intent intent = new Intent("com.example.ORDERED_ACTION");
sendOrderedBroadcast(intent, null); // 第二个参数为权限

本地广播(高效安全)

1
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

5. 注意事项

  • 性能优化:避免高频发送广播,优先使用 LocalBroadcastManager 或 EventBus 等替代方案。
  • 权限控制
    • 发送时指定权限:sendBroadcast(intent, "com.example.PERMISSION")
    • 接收时声明权限:<uses-permission>android:permission
  • ANR 规避onReceive() 方法需在 10秒内完成,复杂操作应交给 Service 或 WorkManager。

6. 源码机制简析

  • AMS 中枢:广播的注册、发送和分发由 ActivityManagerService 统一管理。
  • 跨进程通信:基于 Binder 机制实现,发送方通过 Intent 封装数据,接收方通过 BroadcastReceiver 处理。
  • 有序广播实现:通过优先级(android:priority)排序,高优先级接收器可调用 abortBroadcast() 终止传递。

最佳实践

  • 优先使用 LocalBroadcastManager 替代全局广播(减少安全风险)。
  • 对敏感广播添加权限校验,防止恶意应用拦截。
  • 在 Android 8.0+ 中,使用 JobScheduler 替代静态注册的后台广播监听。

简单封装的实现

定义一个BrodcastManager,用来管理应用中广播的注册、反注册,本地广播、系统广播的发送,各个方法包含异常捕获,增加代码的健壮性。具体实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/**
* 广播管理类
*/
public class BroadcastMgr {
/**
* 发送程序内 broadcast
*
* @param intent 广播内容数据
* @return true 表示广播发送成功,false 表示广播发送失败
*/
public static boolean sendLocalBroadcast(Intent intent) {
try {
return LocalBroadcastManager.getInstance(Utils.getApp()).sendBroadcast(intent);
} catch (Throwable e) {
LogUtils.printStackTrace(e);
}

return false;
}

/**
* 同步发送程序内 broadcast
*
* @param intent 广播内容
*/
public static void sendLocalBroadcastSync(Intent intent) {
try {
LocalBroadcastManager.getInstance(Utils.getApp()).sendBroadcastSync(intent);
} catch (Throwable e) {
LogUtils.printStackTrace(e);
}
}

/**
* 注册程序内 receiver
*
* @param receiver
* @param filter
*/
public static void registerLocalReceiver(BroadcastReceiver receiver, IntentFilter filter) {

try {
LocalBroadcastManager.getInstance(Utils.getApp()).registerReceiver(receiver, filter);
} catch (Throwable e) {
LogUtils.printStackTrace(e);
}
}

/**
* 反注册程序内 receiver
*
* @param receiver
*/
public static void unregisterLocalReceiver(BroadcastReceiver receiver) {
try {
LocalBroadcastManager.getInstance(Utils.getApp()).unregisterReceiver(receiver);
} catch (Throwable e) {
LogUtils.printStackTrace(e);
}
}

/**
* 发送系统全局 broadcast
*
* @param intent 广播内容数据
*/
public static void sendBroadcast(Intent intent) {
try {
Utils.getApp().sendBroadcast(intent);
} catch (Throwable e) {
LogUtils.printStackTrace(e);
}
}

/**
* 发送系统全局 broadcast, 并指定接收者需要指定权限
*
* @param intent 广播内容数据
* @param receiverPermission
*/
public static void sendBroadcast(Intent intent, String receiverPermission) {
try {
Utils.getApp().sendBroadcast(intent, receiverPermission);
} catch (Throwable e) {
LogUtils.printStackTrace(e);
}
}

/**
* 注册系统全局 receiver
*
* @param receiver 广播接收者
* @param filter 广播接收者过滤器
*/
public static void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {

try {
Utils.getApp().registerReceiver(receiver, filter);
} catch (Throwable e) {
LogUtils.printStackTrace(e);
}
}

/**
* 反注册系统全局 receiver
*
* @param receiver 广播接收者
*/
public static void unregisterReceiver(BroadcastReceiver receiver) {
try {
Utils.getApp().unregisterReceiver(receiver);
} catch (Throwable e) {
LogUtils.printStackTrace(e);
}
}
}

说明:

  1. Utils.getApp()返回的是Application Context对象;

  2. 使用LocalBroadcastManager需添加androidx.legacy:legacy-support-v4:1.0.0以来,因为最新的 androidx依赖包中已经将LocalBroadcastManager移除了,为什么移除呢,因为已经有更好的替代方案:如 LiveData、EventBus等;

相关文章