大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
应用调用RegisterReciever,实质是调用的ContextImpl的registerReceiver,接下来跟一下这个流程:
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
其中receiver,即应用中自定义的receiver。
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), 0);
}
即此处的参数:
参数 | 值 |
---|---|
receiver | 即应用中已定义的receiver |
filter | 应用中的filter |
broadcastPermission | null |
scheduler | null |
该函数中新增了两个参数broadcastPermission和scheduler。
- broadcastPermission:对广播者增加了权限控制,只有拥有对应权限的广播者发出的广播才能被此接收者接收;
- scheduler:BroacastReceiver对象的onReceive函数可调度到scheduler所在的线程中执行。
接下来是registerReceiverInternal函数:
registerReceiverInternal
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context, int flags) {
//创建一个IIntentReciever对象
IIntentReceiver rd = null;
if (receiver != null) {
if (mPackageInfo != null && context != null) {
if (scheduler == null) { //没有scheduler,则默认使用主线程的Handler
scheduler = mMainThread.getHandler();
}
rd = mPackageInfo.getReceiverDispatcher(
receiver, context, scheduler,
mMainThread.getInstrumentation(), true);
} else {
if (scheduler == null) {
scheduler = mMainThread.getHandler();
}
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
}
}
try {
final Intent intent = ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
该函数中的参数值:
参数 | 值 |
---|---|
receiver | 应用中自定义的receiver |
userId | getUserId的返回值 |
filter | 应用中的filter |
broadcastPermission | null |
scheduler | null |
context |
getOuterContext()。Context家族中真正干活的是ContextImpl,而其代理对象可以是Application或者Actiivity等,getOuterContext就返回的是这个代理。如果是在Activity中调用的registerReceiver,那此处的context就是Activity. |
flags | 0 |
此函数中else中对rd的赋值:
rd = new LoadedApk.ReceiverDispatcher(
receiver, context, scheduler, null, true).getIIntentReceiver();
先看LoadedApk.ReceiverDispatcher构造函数
/*参数解读:
receiver---应用中的receiver
context---调用registerReceiver的Activity
activityThread---null
instrumentation---null
registered --- true
*/
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);
mReceiver = receiver;
mContext = context;
mActivityThread = activityThread;
mInstrumentation = instrumentation;
mRegistered = registered;
mLocation = new IntentReceiverLeaked(null);
mLocation.fillInStackTrace();
}
注意到其中有个变量mIIntentReceiver:
final IIntentReceiver.Stub mIIntentReceiver;
IIntentReceiver是个interface,关系图谱:
由上面的关系图可知:
- BrocastReceiver内部有一个PendingResult类,该类是用于异步处理广播信息的。如当BroacastReceiver收到广播时,其onReceive函数被调用,一般都是直接在该函数里处理广播。不过,若广播处理比较耗时,可以采用异步的方式进行处理,即先调用BroadcastReceiver的goAsync函数得到一个PendingResult对象,然后将该对象放到工作线程中去处理,这样onReceive函数就可以立即返回而不至于耽误太长时间。工作线程处理完这条广播后,需要调用PendingResult的finish函数来完成整个广播的处理流程。
- 广播由AMS发出,而处理却在另一个进程中进行。整个过程一定涉及进程间通信,虽然在BroadcastReceiver定义了了一个广播接收者,但是它与Binder没有任何关系,故其不直接参与进程间通信。与之相反的是,IIntentReceiver接口和Binder密切相关,故可知广播的接收者是由IIntentReceiver接口来完成的。在整个流程中,首先接收到来自AMS的广播的将是该接口的Bn端,即LoadedApk.ReceiverDispatcher.InnerReceiver。
而InnerReceiver类的具体实现:
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) {
final LoadedApk.ReceiverDispatcher rd;
if (intent == null) {
Log.wtf(TAG, "Null intent received");
rd = null;
} else {
rd = mDispatcher.get();
}
if (ActivityThread.DEBUG_BROADCAST) {
int seq = intent.getIntExtra("seq", -1);
Slog.i(ActivityThread.TAG, "Receiving broadcast " +
intent.getAction()
+ " seq=" + seq + " to " + (rd != null ? rd.mReceiver : null));
}
if (rd != null) {
rd.performReceive(intent, resultCode, data, extras,
ordered, sticky, sendingUser);
} else {
// The activity manager dispatched a broadcast to a registered
// receiver in this process, but before it could be delivered the
// receiver was unregistered. Acknowledge the broadcast on its
// behalf so that the system's broadcast sequence can continue.
if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
"Finishing broadcast to unregistered receiver");
IActivityManager mgr = ActivityManager.getService();
try {
if (extras != null) {
extras.setAllowFds(false);
}
mgr.finishReceiver(this, resultCode, data, extras, false,
intent.getFlags());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
}
而rd =new LoadedApk.ReceiverDispatcher(receiver, context, scheduler, null, true).getIIntentReceiver();中的getIIntentReceiver就是返回的mIIntentReceiver变量。
小结
registerReceiverInternal函数主要完成了2个工作:
- 创建了一个IIntentReceiver对象
- 调用AMS的registerReceiver函数
接下来看AMS的registerReceiver函数:
AMS.registerReceiver
//ContextImpl.java
final Intent intent = ActivityManager.getService().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
broadcastPermission, userId, flags);
//ActivityManagerService.java
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
//....
}
由上可知,传入AMS.registerReceiver的参数表:
参数 | 值 |
---|---|
caller | 应用主线程的ApplicationThread |
callerPackage | 进程创建时new ContextImpl时的package |
receiver | 即IIntentReceiver,接收来自AMS的Bn端 |
filter | 应用传入的filter |
permission | null |
userId |
进程的userId |
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
int flags) {
enforceNotIsolatedCaller("registerReceiver");
ArrayList<Intent> stickyIntents = null;
ProcessRecord callerApp = null;
...
int callingUid;
int callingPid;
synchronized(this) {
if (caller != null) {
callerApp = getRecordForAppLocked(caller);
if (callerApp == null) { //系统不允许未注册的进程注册动态receiver
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when registering receiver " + receiver);
}
//检查调用进程是否有callerPackage信息,如果没有,抛出异常
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();
}
....//instantApp的处理
//从系统的Sticky Intent中查询匹配IntentFilter的intent,结果保存到allSticky中
Iterator<String> actions = filter.actionsIterator();
if (actions == null) {
ArrayList<String> noAction = new ArrayList<String>(1);
noAction.add(null);
actions = noAction.iterator();
}
// Collect stickies of users
int[] userIds = { UserHandle.USER_ALL, UserHandle.getUserId(callingUid) };
while (actions.hasNext()) {
String action = actions.next();
for (int id : userIds) {
ArrayMap<String, ArrayList<Intent>> stickies =
mStickyBroadcasts.get(id);
if (stickies != null) {
ArrayList<Intent> intents = stickies.get(action);
if (intents != null) {
if (stickyIntents == null) {
stickyIntents = new ArrayList<Intent>();
}
stickyIntents.addAll(intents);
}
}
}
}
}
//在stickyIntents中查询和IntentFilter匹配的intent
ArrayList<Intent> allSticky = null;
if (stickyIntents != null) {
final ContentResolver resolver = mContext.getContentResolver();
// Look for any matching sticky broadcasts...
for (int i = 0, N = stickyIntents.size(); i < N; i++) {
Intent intent = stickyIntents.get(i);
// Don't provided intents that aren't available to instant apps.
...//Instant APP的相关处理
// 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<Intent>();
}
allSticky.add(intent);
}
}
}
//如果allSticky不为空,则选择第一个Intent作为本函数的返回值
// The first sticky in the list is returned directly back to the client.
Intent sticky = allSticky != null ? allSticky.get(0) : null;
//如果没有设置接收者,则直接返回Sticky的intent
if (receiver == null) {
return sticky;
}
synchronized (this) {
if (callerApp != null && (callerApp.thread == null
|| callerApp.thread.asBinder() != caller.asBinder())) {
// Original caller already died
//之前的调用者所在进程已经die了
return null;
}
//在mRegisteredReceivers中查询receiver对应的IBinder对象的ReceiverList
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {//如果是首次调用,rl = null
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
rl.app.receivers.add(rl);
} else {
try {
//监听广播接收者所在进程的死亡消息
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
//将rl保存到mRegisterReceivers中
mRegisteredReceivers.put(receiver.asBinder(), rl);
} else if (...) {
......//其他情况,抛出异常信息
}
//新建BroadcastFilter对象
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
permission, callingUid, userId, instantApp, visibleToInstantApps);
//保存到rl中
rl.add(bf);
mReceiverResolver.addFilter(bf);
// Enqueue broadcasts for all existing stickies that match
// this filter.
//allSticky不为空,表示有Sticky的intent,需要立即调度广播发送
if (allSticky != null) {
ArrayList receivers = new ArrayList();
receivers.add(bf);
final int stickyCount = allSticky.size();
for (int i = 0; i < stickyCount; i++) {
Intent intent = allSticky.get(i);
BroadcastQueue queue = broadcastQueueForIntent(intent);
//为每一个需要发送的广播创建一个BroadcastRecord对象
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;
}
这段code中有几个变量需要说明:
- mRegisteredReceivers:
/**
* Keeps track of all IIntentReceivers that have been registered for broadcasts.
* Hash keys are the receiver IBinder, hash value is a ReceiverList.
*/
final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
HashMap变量,用于保存IIntentReceiver和对应ReceiverList的关系,即使用接收者(receiver)的IBinder为key,value是receiver对应的ReceiverList(因为一个receiver可能对应多个IntentFilter,所以用List来保存IntentFilter)。
- mReceiverResolver
/**
* Resolver for broadcast intents to registered receivers.
* Holds BroadcastFilter (subclass of IntentFilter).
*/
final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
= new IntentResolver<BroadcastFilter, BroadcastFilter>() {
...//实现部分方法
}
保存receiver设置的过滤条件(IntentFilter)
关联如下:
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/194627.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...