Android 系统广播监听模块深度剖析
本人掘金号,欢迎点击关注:掘金号地址
本人公众号,欢迎点击关注:公众号地址
一、广播监听模块基础概念
1.1 广播机制概述
Android 系统广播监听模块是基于消息驱动的事件分发系统,它允许应用程序之间或应用与系统之间进行跨进程通信。广播的本质是一种异步通信机制,通过发送特定的 Intent 对象,系统或应用可以通知其他组件某些事件已经发生。
1.2 广播类型
- 普通广播:异步发送,所有注册的接收器都能接收到,无法被拦截。
- 有序广播:同步发送,接收器按优先级顺序接收,高优先级接收器可以拦截广播。
- 粘性广播:已弃用,发送后会一直存在,新注册的接收器也能接收到。
二、广播注册流程分析
2.1 动态注册流程
当应用通过Context.registerReceiver()方法动态注册广播接收器时,具体执行流程如下:
java
// Context.java
public abstract Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter);
// ContextImpl.java
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
// 验证权限
final String resolvedType = verifyAndAddActionFilter(filter, receiver, callerPackage);
// 获取ActivityManagerService代理
final IActivityManager mgr = ActivityManager.getService();
try {
// 调用AMS的注册方法
return mgr.registerReceiver(this, mMainThread.getThreadHandler(), receiver,
filter, broadcastPermission, resolvedType);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在上述代码中:
verifyAndAddActionFilter方法用于验证和解析 IntentFilter。- 通过
ActivityManager.getService()获取 AMS 代理,然后调用 AMS 的registerReceiver方法进行注册。
2.2 AMS 注册处理
AMS 中registerReceiver方法的实现如下:
java
// ActivityManagerService.java
@Override
public Intent registerReceiver(IApplicationThread caller,
IIntentReceiver receiver,
IntentFilter filter,
String broadcastPermission,
String callingPackage,
String resolvedType) {
// 检查权限
enforceCrossUserPermission(BROADCAST_RECEIVE, UserHandle.getCallingUserId(), false,
"registerReceiver");
synchronized (this) {
// 获取或创建注册信息
ReceiverList rl = registerReceiverLocked(callerApp,
callingPackage,
receiver,
filter,
broadcastPermission,
callingUid,
userId);
// 将注册信息添加到全局列表
mReceiverResolver.addFilter(filter, rl, rl.appInfo.uid,
rl.appInfo.packageName,
callingUid,
userId);
return null;
}
}
private ReceiverList registerReceiverLocked(...) {
// 创建ReceiverList对象
ReceiverList rl = new ReceiverList(callerApp, callingPackage,
receiver, registered);
// 加入到应用的注册列表
if (callerApp != null) {
rl.app = callerApp;
callerApp.receivers.add(rl);
}
return rl;
}
在 AMS 的注册流程中:
- 首先进行权限检查。
- 然后通过
registerReceiverLocked方法创建ReceiverList对象,该对象包含了注册的接收器信息。 - 最后将
ReceiverList添加到全局的mReceiverResolver中,以便后续广播匹配使用。
2.3 静态注册流程
静态注册是通过在AndroidManifest.xml文件中声明<receiver>标签实现的。系统在应用安装时解析AndroidManifest.xml,并将注册信息存储在PackageParser中。
xml
<receiver
android:name=".MyReceiver"
android:exported="true">
<intent-filter>
<action android:name="com.example.ACTION_EXAMPLE" />
</intent-filter>
</receiver>
系统在安装应用时,会通过PackageParser解析上述配置,并将信息存储到PackageParser.Activity对象中。
java
// PackageParser.java
public Package parsePackage(File packageFile, int flags) {
// 解析XML文件
final XmlResourceParser parser = Xml.newPullParser();
parser.setInput(new FileInputStream(packageFile), null);
// 遍历XML节点
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.START_TAG) {
if (parser.getName().equals("receiver")) {
// 解析<receiver>标签
final Activity receiver = parseActivity(parser, flags,
false, false, true);
// 添加到Package对象
pkg.activities.add(receiver);
}
}
}
return pkg;
}
三、广播发送流程分析
3.1 普通广播发送
应用通过Context.sendBroadcast()方法发送普通广播:
java
// Context.java
public abstract void sendBroadcast(Intent intent);
// ContextImpl.java
@Override
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
// 设置默认发送者
intent = intent != null ? intent : new Intent();
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
// 调用AMS的发送方法
mActivityManager.broadcastIntent(this, null, intent, null,
null, 0, null, null, null,
AppOpsManager.OP_NONE, null, false, false,
getUserId());
}
在上述代码中:
- 首先对 Intent 进行一些默认设置。
- 然后通过 AMS 代理调用
broadcastIntent方法发送广播。
3.2 AMS 广播分发处理
AMS 的broadcastIntent方法实现如下:
java
// ActivityManagerService.java
@Override
public final int broadcastIntent(IApplicationThread caller,
String callerPackage,
Intent intent,
String resolvedType,
IIntentReceiver resultTo,
String resultData,
Bundle resultExtras,
int flags,
String[] requiredPermissions,
int appOp,
Bundle bOptions,
boolean serialized,
boolean sticky,
int userId) {
enforceNotIsolatedCaller("broadcastIntent");
synchronized (this) {
// 解析Intent
intent = verifyBroadcastLocked(intent);
// 检查权限
final int callingUid = Binder.getCallingUid();
enforceCallingPermission(android.Manifest.permission.BROADCAST,
"broadcastIntent");
// 处理粘性广播
if (sticky) {
// 存储粘性广播
stickyIntents.put(intent, new BroadcastRecord(intent, callerApp,
callerPackage, callingUid,
callingPid, userId,
requiredPermissions, appOp,
null, null, null,
null, 0, false, false,
false, null, false, false));
}
// 发送广播
return broadcastIntentLocked(callerApp, callerPackage, intent, resolvedType,
resultTo, resultData, resultExtras, flags,
requiredPermissions, appOp, bOptions, serialized,
sticky, callingUid, userId);
}
}
private int broadcastIntentLocked(...) {
// 查找匹配的接收器
final List<ResolveInfo> receivers = collectReceiverComponents(intent, resolvedType,
callingUid, userId);
// 创建广播记录
final BroadcastRecord r = new BroadcastRecord(intent, callerApp,
callerPackage, callingUid,
callingPid, userId,
requiredPermissions, appOp,
receivers, resultTo, resultData,
resultExtras, flags,
serialized, sticky, false,
null, false, false);
// 分发广播
final boolean replaced = enqueueParallelBroadcastLocked(r);
// 启动广播处理线程
scheduleBroadcastsLocked();
return ActivityManager.RESULT_OK;
}
在 AMS 的广播分发流程中:
- 首先进行权限检查和 Intent 解析。
- 然后通过
collectReceiverComponents方法查找匹配的接收器。 - 创建
BroadcastRecord对象记录广播信息。 - 通过
enqueueParallelBroadcastLocked方法将广播加入队列,并通过scheduleBroadcastsLocked方法启动广播处理线程。
四、广播接收流程分析
4.1 异步广播接收
当 AMS 完成广播分发后,会通过ActivityThread将广播事件发送到应用主线程。
java
// ActivityThread.java
class H extends Handler {
public static final int EXECUTE_TRANSACTION = 159;
public static final int BROADCAST_INTENT = 160;
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case BROADCAST_INTENT:
// 处理广播事件
handleBroadcast((BroadcastRecord) msg.obj);
break;
// 其他消息处理...
}
}
}
private void handleBroadcast(BroadcastRecord r) {
final int N = r.receivers.size();
for (int i = 0; i < N; i++) {
final ReceiverList rec = r.receivers.get(i);
final int delivery = rec.deliver;
if (delivery > 0) {
// 创建广播分发器
final ReceiverDispatcher dispatcher = createReceiverDispatcher(
rec.receiverList, r, i,
r.callingPid, r.callingUid,
getPermissionsController());
rec.dispatcher = dispatcher;
// 触发接收回调
dispatcher.performReceive(r.intent, r.resultCode, r.resultData,
r.resultExtras, r.ordered,
r.initialSticky, r.userId);
}
}
}
在上述代码中:
ActivityThread的H类接收广播事件消息。- 通过
handleBroadcast方法遍历匹配的接收器列表。 - 为每个接收器创建
ReceiverDispatcher对象。 - 调用
performReceive方法触发接收器的onReceive回调。
4.2 有序广播接收
有序广播的处理流程与异步广播类似,但在 AMS 中会按照优先级顺序依次分发广播,并且高优先级接收器可以通过abortBroadcast方法拦截广播。
java
// ActivityManagerService.java
private int broadcastIntentLocked(...) {
if (serialized) {
// 有序广播处理
final boolean replaced = enqueueOrderedBroadcastLocked(r);
scheduleBroadcastsLocked();
} else {
// 异步广播处理
final boolean replaced = enqueueParallelBroadcastLocked(r);
scheduleBroadcastsLocked();
}
return ActivityManager.RESULT_OK;
}
private boolean enqueueOrderedBroadcastLocked(BroadcastRecord r) {
// 将广播加入有序队列
r.state = BroadcastRecord.STATE_PENDING;
r.nextReceiver = 0;
mOrderedBroadcasts.add(r);
return true;
}
在有序广播处理中:
- AMS 将广播加入
mOrderedBroadcasts队列。 - 依次分发广播,每次只处理一个接收器。
- 接收器可以通过
abortBroadcast方法设置广播的aborted标志,从而拦截广播。
五、广播匹配机制
5.1 IntentFilter 匹配规则
IntentFilter用于定义广播接收的条件,其匹配规则基于Intent的action、category和data属性。
java
// IntentFilter.java
public boolean match(Intent intent, String resolvedType, int matchFlags) {
// 检查action匹配
if (mActions != null) {
final String intentAction = intent.getAction();
if (intentAction != null) {
for (int i = 0; i < mActions.size(); i++) {
if (mActions.get(i).equals(intentAction)) {
// 找到匹配的action
if ((matchFlags & MATCH_CATEGORY_SCHEME) != 0) {
// 检查category和scheme匹配
if (matchCategoriesAndSchemes(intent, resolvedType,
matchFlags)) {
return true;
}
} else {
return true;
}
}
}
}
}
return false;
}
private boolean matchCategoriesAndSchemes(Intent intent,
String resolvedType,
int matchFlags) {
// 检查category匹配
if (mCategories != null) {
final String[] categories = intent.getCategories();
if (categories != null) {
for (int i = 0; i < mCategories.size(); i++) {
boolean found = false;
for (int j = 0; j < categories.length; j++) {
if (mCategories.get(i).equals(categories[j])) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
}
}
// 检查data匹配
if (mDataSchemes != null || mDataAuthorities != null || mDataPaths != null) {
// 解析Intent的data
final Uri data = intent.getData();
if (data != null) {
return matchData(data, resolvedType, matchFlags);
}
}
return true;
}
在上述代码中:
match方法首先检查Intent的action是否匹配。- 如果
action匹配,再根据matchFlags检查category和data是否匹配。 matchCategoriesAndSchemes方法具体执行category和data的匹配逻辑。
5.2 AMS 匹配逻辑
AMS 在分发广播时,通过collectReceiverComponents方法查找匹配的接收器:
java
// ActivityManagerService.java
private List<ResolveInfo> collectReceiverComponents(Intent intent,
String resolvedType,
int callingUid,
int userId) {
final ArrayList<ResolveInfo> results = new ArrayList<>();
// 查找动态注册的接收器
final int matchingSize = mReceiverResolver.queryIntent(intent, resolvedType,
false, userId, results);
// 查找静态注册的接收器
final List<PackageParser.Activity> receivers =
mPackageManager.queryIntentReceivers(intent, resolvedType,
PackageManager.MATCH_ALL, userId);
for (PackageParser.Activity receiver : receivers) {
final ResolveInfo info = new ResolveInfo();
info.activityInfo = receiver.info;
results.add(info);
}
return results;
}
在 AMS 的匹配流程中:
- 首先通过
mReceiverResolver查找动态注册的接收器。 - 然后通过
PackageManager查找静态注册的接收器。 - 将所有匹配的接收器信息封装成
ResolveInfo对象并返回。
六、广播接收器生命周期管理
6.1 动态接收器生命周期
动态注册的广播接收器的生命周期与注册它的组件(如 Activity)相关联。当组件销毁时,应及时调用Context.unregisterReceiver()方法注销接收器。
java
// Context.java
public abstract void unregisterReceiver(BroadcastReceiver receiver);
// ContextImpl.java
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
final IActivityManager mgr = ActivityManager.getService();
try {
// 调用AMS的注销方法
mgr.unregisterReceiver(this, receiver);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在 AMS 中,unregisterReceiver方法会从全局注册列表中移除对应的接收器信息。
6.2 静态接收器生命周期
静态注册的接收器在应用安装时注册,其生命周期与应用的生命周期相关。系统在需要时会自动创建和销毁静态接收器实例。
七、广播性能优化
7.1 减少不必要的注册
避免在频繁创建和销毁的组件中动态注册广播接收器,尽量在应用启动时进行注册。
7.2 优化 IntentFilter
只定义必要的action、category和data匹配条件,减少不必要的匹配计算。
7.3 避免阻塞主线程
在onReceive方法中避免执行耗时操作,如需处理耗时任务,应启动 Service 或使用异步任务。
八、总结与展望
8.1 总结
通过对 Android 系统广播监听模块的源码级分析,我们深入了解了广播的注册、发送、接收和匹配机制。广播机制作为 Android 系统中重要的跨进程通信方式,其核心原理包括:
- 注册流程:动态注册通过 AMS 进行全局管理,静态注册在应用安装时解析配置。
- 发送流程:通过 AMS 实现广播的分发和队列管理。
- 接收流程:通过
ActivityThread将广播事件发送到应用主线程,并触发接收器回调。 - 匹配机制:基于
IntentFilter的规则匹配,结合动态和静态注册信息查找接收器。
8.2 展望
随着 Android 系统的不断发展,广播机制也在不断优化:
- 权限管理加强:Android 系统对广播权限的管理越来越严格,未来可能会进一步限制敏感广播的使用。
- 性能优化: