Android Broadcast原理分析之registerReceiver详解
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
enforceNotIsolatedCaller("registerReceiver");
ArrayList
ProcessRecord callerApp = null;
final boolean visibleToInstantApps
= (flags & Context.RECEIVER_VISIBLE_TO_INSTANT_APPS) != 0;
int callingUid;
int callingPid;
boolean instantApp;
synchronized(this) {
if (caller != null) {
// 正常来讲caller是发起binder call的客户端进程对应的ApplicationThread对象
// 如果为null则抛异常
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when registering receiver " + receiver);
}
if (callerApp.info.uid != SYSTEM_UID &&
!callerApp.pkgList.containsKey(callerPackage) &&
!"android".equals(callerPackage)) {
throw new SecurityException("Given caller package " + callerPackage
+ " is not running in process " + callerApp);
}
callingUid = callerApp.info.uid;
callingPid = callerApp.pid;
} else {
callerPackage = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
}
// 判断caller是否为instant app
instantApp = isInstantApp(callerApp, callerPackage, callingUid);
userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
// 获取广播注册的filter中的action封装到list中
Iterator
if (actions == null) {
ArrayList
noAction.add(null);
actions = noAction.iterator();
}
// mStickyBroadcasts是一个二级map
// 一级key是userId,二级key是广播对应的action,value是广播对应intent的list(一般只有一个intent)
// 这里是为了查询对于当前user,本次注册的所有action对应的sticky广播的intent
int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
while (actions.hasNext()) {
String action = actions.next();
for (int id : userIds) {
ArrayMap
if (stickies != null) {
ArrayList
if (intents != null) {
if (stickyIntents == null) {
stickyIntents = new ArrayList
}
stickyIntents.addAll(intents);
}
}
}
}
}
ArrayList
// 这里不为null表示本次注册的广播中有sticky广播
if (stickyIntents != null) {
final ContentResolver resolver = mContext.getContentResolver();
// 查找匹配的sticky广播
for (int i = 0, N = stickyIntents.size(); i < N; i++) {
Intent intent = stickyIntents.get(i);
// 如果caller是instant app,且intent的flag不允许对instant可见,则跳过
if (instantApp &&
(intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
continue;
}
// If intent has scheme "content", it will need to acccess
// provider that needs to lock mProviderMap in ActivityThread
// and also it may need to wait application response, so we
// cannot lock ActivityManagerService here.
if (filter.match(resolver, intent, true, TAG) >= 0) {
if (allSticky == null) {
allSticky = new ArrayList
}
allSticky.add(intent);
}
}
}
// 直接把最近的一个匹配到的sticky广播返回
Intent sticky = allSticky != null ? allSticky.get(0) : null;
// 广播注册的时候receiver是可以为null的,这种情况下这里直接return
if (receiver == null) {
return sticky;
}
synchronized (this) {
// 校验caller进程是否正常
if (callerApp != null && (callerApp.thread == null
|| callerApp.thread.asBinder() != caller.asBinder())) {
// Original caller already died
return null;
}
// mRegisteredReceivers中存放了所有的已注册的receiver
// 每个BroadcastReceiver对应一个InnerReceiver,即Binder对象
// binder对象做key,value是ReceiverList
// ReceiverList是一个ArrayList
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
try {
// 如果是新创建的receiver,还需要linkToDeath
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
// 放入mRegisteredReceivers
mRegisteredReceivers.put(receiver.asBinder(), rl);
} else if (rl.uid != callingUid) {
throw new IllegalArgumentException(
"Receiver requested to register for uid " + callingUid
+ " was previously registered for uid " + rl.uid
+ " callerPackage is " + callerPackage);
} else if (rl.pid != callingPid) {
throw new IllegalArgumentException(
"Receiver requested to register for pid " + callingPid
+ " was previously registered for pid " + rl.pid
+ " callerPackage is " + callerPackage);
} else if (rl.userId != userId) {
throw new IllegalArgumentException(
"Receiver requested to register for user " + userId
+ " was previously registered for user " + rl.userId
+ " callerPackage is " + callerPackage);
}
// 每一个IntentFilter对应一个BroadcastFilter
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
// receiverList中存放了通过这个receiver注册的所有的filter
// 每调用一次register就会add一次
rl.add(bf);
// mReceiverResolver中存放所有的BroadcastFilter
mReceiverResolver.addFilter(bf);
// 有匹配的sticky广播,则直接开始调度派发
if (allSticky != null) {
ArrayList receivers = new ArrayList();
receivers.add(bf);
// 对于每一个sticky广播,创建BroadcastRecord并入队(并行)
final int stickyCount = allSticky.size();
for (int i = 0; i < stickyCount; i++) {
Intent intent = allSticky.get(i);
// 根据flag是否有FLAG_RECEIVER_FOREGROUND判断入队是前台还是后台队列
BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, null,
null, -1, -1, false, null, null, AppOpsManager.OP_NONE, null, receivers,
null, 0, null, null, false, true, true, -1);
// 入队,并行队列
queue.enqueueParallelBroadcastLocked(r);
// 启动广播的调度,也就是开始派发广播
queue.scheduleBroadcastsLocked();
}
}
return sticky;
}
}
- .NET Core系列之MemoryCache 初识
- 007手机一键Root(安机网一键Root) v3.0 官方最新版 一键ROOT您的Android手机
- 12306密码被盗了怎么办?12306密码外泄解决方法
- 12个字的qq网名
- 150M迷你型无线路由器怎么设置?
- 192.168.1.1打不开怎么办?路由器192.168.1.1打不开的原因以及解决办法
- 2011年电子报合订本 电子报 编辑部 中文 PDF版 [84M]
- 2015年1月15日小米新旗舰发布会现场图文直播
- 2016.3.1vivo Xplay5新品发布会现场视频直播 优酷直播
- 2016华为P9发布会视频直播地址 4月15日华为P9国行发布会直播
相关文章
- Android中的广播(BroadCast)详细介绍
- Action Movie FX(电影动作特效制作工具) for Android V2.5 安卓版
- Android AlertDialog六种创建方式案例详解
- Android四大组件之broadcast广播详解
- Android使用Rotate3dAnimation实现3D旋转动画效果的实例代码
- Android 实现自定义圆形进度条的三种常用方法
- 99直播app for Android V1.3.6 安卓版
- Android中的缓存与文件存储目录详解
- qq音乐HD版 for Android v6.5.011 安卓版
- Android 文件下载三种基本方式