hi,上一节我们主要分析了broadcast的发送部分,本节我们来分析一下接受部分,即一般我们作为一个广播接受者是怎么一步步被AMS发送过来的信息的。
一般我们注册成为一个广播监听接受者都是调用Context.java中的如下方法:
public abstract Intent registerReceiver(@Nullable 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) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), 0);
}
最后会调用到registerReceiverInternal方法:
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
//构造出IIntentReceiver
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
}
}
try {
//调用 ActivityManager对应的registerReceiver方法来注册到AMS且把rd传递进去
final Intent intent = ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
return intent;
}
}
这里主要其实就分为2部分:
1、构造出一个IIntentReceiver对象
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
这里会调用到getReceiverDispatcher方法:
public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,
Context context, Handler handler,
Instrumentation instrumentation, boolean registered) {
synchronized (mReceivers) {
LoadedApk.ReceiverDispatcher rd = null;
ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;
//判断是否已经缓存了对应的IIntentReceiver对象
if (registered) {
map = mReceivers.get(context);
if (map != null) {
rd = map.get(r);
}
}
//没有缓存则直接进行构造
if (rd == null) {
rd = new ReceiverDispatcher(r, context, handler,
instrumentation, registered);
if (registered) {
if (map == null) {
map = new ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();
mReceivers.put(context, map);
}
map.put(r, rd);
}
} else {
rd.validate(context, handler);
}
rd.mForgotten = false;
return rd.getIIntentReceiver();
}
}
这里应该比较容易看懂,就是简单的判断是否有缓存,没有就再进行构造,但是这里要注意哦,返回要求是IIntentReceiver类型,而new的是一个ReceiverDispatcher类型,那么这个IIntentReceiver是哪里构造来的呢?这里就要看ReceiverDispatcher构造源码了:
ReceiverDispatcher(BroadcastReceiver receiver, Context context,
Handler activityThread, Instrumentation instrumentation,
boolean registered) {
if (activityThread == null) {
throw new NullPointerException("Handler must not be null");
}
mIIntentReceiver = new InnerReceiver(this, !registered);//这个地方new出来了这个InnerReceiver对象
mReceiver = receiver;
mContext = context;
mActivityThread = activityThread;
mInstrumentation = instrumentation;
mRegistered = registered;
mLocation = new IntentReceiverLeaked(null);
mLocation.fillInStackTrace();
}
这里的
final static class InnerReceiver extends IIntentReceiver.Stub {
final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
final LoadedApk.ReceiverDispatcher mStrongRef;
InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
mStrongRef = strong ? rd : null;
}
@Override
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean ordered, boolean sticky, int sendingUser)
//省略部分
}
}
}
这里最后发现InnerReceiver其实是实现了IIntentReceiver.Stub 这个跨进程对象的一个实体,也就是我们说的Binder的实现端,服务端,因为这里我们注册广播属于接受者,当然是由客户端调用到我们这端,所以当然就是服务端。
2、调用 ActivityManager对应的registerReceiver方法来注册到AMS且把rd传递进去
这里就是调用了:
ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
这个方法一看大家就应该知道最后会跨进程调用到AMS中:
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
//省略部分
synchronized (this) {
//省略部分
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
//根据receiver创建出一个ReceiverList,为啥是个List?因为很有可能一个Receiver可能接受多个广播
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
//省略部分
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
//省略部分
//构造出对应的BroadcastFilter,主要为了方便到时候发端方便寻找到这个接受端
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
if (rl.containsFilter(filter)) {
} else {
rl.add(bf);//bf被添加到了对应的rl
mReceiverResolver.addFilter(bf);
}
//省略部分
}
}
这里其实就是在AMS中把广播的对应ReceiverList创建出来,而且与Filter进行映射好,这样广播接受者在AMS中的注册就算完成
总结图如下:
最后宣传一下课程:
[入门课,实战课,跨进程专题
ps需要学习深入framework课程和课程优惠
(可以加我qq:2102309716 优惠购买)