这篇“Android广播Broadcast的启动流程是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Android广播Broadcast的启动流程是什么”文章吧。
广播的注册
我们常在
或
Activity
、甚至
Service
中调用
Application
函数来注册动态广播,该函数其实来自它们共同的父类
registerReceiver
中。
ContextWrapper
是
ContextWrapper
的子类,我们会在介绍
Context
的文章介绍它们的关系。
Context
public Intent registerReceiver(
BroadcastReceiver receiver, IntentFilter filter) {
return mBase.registerReceiver(receiver, filter);
}
这里
类型的
Context
,在
mBase
的创建过程实际被赋值为
Activity
实例。
ContextImpl
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
return registerReceiverInternal(receiver, getUserId(),
filter, broadcastPermission, scheduler, getOuterContext(), 0);
}
经过
重载函数,调用了
registerReceiver
函数。
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) {
if (scheduler == null) {
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().registerReceiverWithFeature(
mMainThread.getApplicationThread(), mBasePackageName, getAttributionTag(), rd,
filter, broadcastPermission, userId, flags);
if (intent != null) {
intent.setExtrasClassLoader(getClassLoader());
intent.prepareToEnterProcess();
}
return intent;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
分析一:
传递进来的
不为
BroadcastReceiver
,
null
类型的
LoadedApk
只要应用进程启动,该属性就会被赋值,
mPackageInfo
这里指向
context
。
Activity
为
scheduler
,赋值为主线程的
null
类型
H
对象。分析一,主要通过上面的变量来获得
mH
类型
IIntentReceiver
对象。
rd
函数先从缓存检测是否有相同类型的
getReceiverDispatcher
对应的
BroadcastReceiver
。没有的话,则新建并缓存起来。 一个
ReceiverDispatcher
对应多个
context
,而一个
BroadcastReceiver
对应用一个
BroadcastReceiver
。
ReceiverDispatcher
是
ReceiverDispatcher
的静态内部类,其内部还有一个
LoadedDispatcher
类型本地实现静态类
AIDL
。在
InnerReceiver
的构造函数中会创建
ReceiverDispatcher
的实例。
InnerReceiver
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;
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();
}
}
回到
函数的分析二,调用了
registerReceiverInternal
的
AMS
函数。
registerReceiverWithFeature
该函数是
整个注册过程结束的地方,根据新注册的
Broadcast
,处理粘性广播的发送和当前注册
BroadcastReceiver
的添加。
Receiver
分析一:
粘性广播存储在AMS的
类型的
SparseArray<ArrayMap<String, ArrayList<Intent>>>
中。
mStickyBroadcasts
的
SparseArray
为
key
,而
userId
的
ArrayMap
为
key
,
action
为
value
。即我们可以通过用户id在
Intent
找到当前进程对应所有粘性广播(和针对所有进程的粘性广播),然后根据对应的
mStickyBroadcasts
找到对应的
action
。这里将他们收集到
Intent
集合中。
stickyIntents
分析二:
所有广播的接收者
存储在
BroacastReceiver
类
AMS
类型的
HashMap<IBinder, ReceiverList>
中。这里的
mRegisteredReceivers
类型就是应用进程前面创建的
IBinder
类实例在AMS的引用。因为广播接收者
InnerReceiver
对应一个或多个
BroadcastReceiver
,所以这里通过继承自
Broadcast
的
ArrayList<BroadcastFilter>
来表达这种关系。通过
ReceiverList
来表示当前接收者感兴趣的广播。
BroadcastFilter
分析三:
对匹配到的粘性Intent进入广播队列广播。
public Intent registerReceiverWithFeature(IApplicationThread caller, String callerPackage,
String callerFeatureId, IIntentReceiver receiver, IntentFilter filter,
String permission, int userId, int flags) {
enforceNotIsolatedCaller("registerReceiver");
//粘性Intent
ArrayList<Intent> stickyIntents = null;
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) {
//获得当前引用进程的ProcessRecord
callerApp = getRecordForAppLocked(caller);
...
callingUid = callerApp.info.uid;
callingPid = callerApp.pid;
} else {
callerPackage = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
}
//是否快应用(类似小程序)
instantApp = isInstantApp(callerApp, callerPackage, callingUid);
userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
ALLOW_FULL_ONLY, "registerReceiver", callerPackage);
//分析一:当前注册广播中感兴趣的action列表
Iterator<String> actions = filter.actionsIterator();
if (actions == null) {
ArrayList<String> noAction = new ArrayList<String>(1);
noAction.add(null);
actions = noAction.iterator();
}
//从历史粘性广播中查找与当前注册的action一致的intent
//添加到stickyIntents
// 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);
}
}
}
}
}
//处理content类型的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.
if (instantApp &&
(intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
continue;
}
//当前注册广播IntentFilter是否与action一致的intent的匹配
//处理content类型
if (filter.match(resolver, intent, true, TAG) >= 0) {
if (allSticky == null) {
allSticky = new ArrayList<Intent>();
}
allSticky.add(intent);
}
}
}
//receiver为null,直接返回null或者第一个粘性intent
Intent sticky = allSticky != null ? allSticky.get(0) : null;
if (receiver == null) {
return sticky;
}
synchronized (this) {
...
//分析二:
//从缓存或新建ReceiverList对象,与Receiver绑定
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl == null) {
rl = new ReceiverList(this, callerApp, callingPid, callingUid,
userId, receiver);
if (rl.app != null) {
final int totalReceiversForApp = rl.app.receivers.size();
if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
throw new IllegalStateException("Too many receivers, total of "
+ totalReceiversForApp + ", registered for pid: "
+ rl.pid + ", callerPackage: " + callerPackage);
}
//添加到ProcessRecord记录中
rl.app.receivers.add(rl);
} else {
try {
receiver.asBinder().linkToDeath(rl, 0);
} catch (RemoteException e) {
return sticky;
}
rl.linkedToDeath = true;
}
mRegisteredReceivers.put(receiver.asBinder(), rl);
}
...
//新建BroadcastFilter,并添加到BroadcastList
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, callerFeatureId,
permission, callingUid, userId, instantApp, visibleToInstantApps);
if (rl.containsFilter(filter)) {
...
} else {
rl.add(bf);
//添加到接收者解析器
mReceiverResolver.addFilter(bf);
}
// Enqueue broadcasts for all existing stickies that match
// this filter.
//分析三:对匹配到action的粘性广播进行广播
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 r = new BroadcastRecord(queue, intent, null,
null, null, -1, -1, false, null, null, OP_NONE, null, receivers,
null, 0, null, null, false, true, true, -1, false,
false /* only PRE_BOOT_COMPLETED should be exempt, no stickies */);
queue.enqueueParallelBroadcastLocked(r);
queue.scheduleBroadcastsLocked();
}
}
return sticky;
}
}
广播的解注册
回到
的
ContextWrapper
函数。
unregisterReceiver
#ContextWrapper
public void unregisterReceiver(BroadcastReceiver receiver) {
mBase.unregisterReceiver(receiver);
}
#ContextImpl
public void unregisterReceiver(BroadcastReceiver receiver) {
if (mPackageInfo != null) {
IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(
getOuterContext(), receiver);
try {
ActivityManager.getService().unregisterReceiver(rd);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} else {
throw new RuntimeException("Not supported in system context");
}
}
这里通过
和
receiver
获得
context
实例
IIntentReceiver
,然后调用AMS的
rd
函数。其中
unregisterReceiver
的
LoadedApk
函数,主要是从
forgetReceiverDispatcher
获取
mReceivers
的实例,并将
IIntentReceiver
对应的内容从缓存移除。
receiver
AMS的
函数。主要是将注册过程添加到
unregisterReceiver
、
mRegisteredReceivers
.Receivers、
ProcessProcess
中对应的内容移除。并终止正在发送的广播。
mReceiverResolver
public void unregisterReceiver(IIntentReceiver receiver) {
...
final long origId = Binder.clearCallingIdentity();
try {
boolean doTrim = false;
synchronized(this) {
//获得当前对应的ReceiverList
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl != null) {
//默认情况为null,看看广播发送是否会赋值
//从处理逻辑来看,就是广播内容
final BroadcastRecord r = rl.curBroadcast;
if (r != null && r == r.queue.getMatchingOrderedReceiver(r)) {
final boolean doNext = r.queue.finishReceiverLocked(
r, r.resultCode, r.resultData, r.resultExtras,
r.resultAbort, false);
if (doNext) {
doTrim = true;
r.queue.processNextBroadcast(false);
}
}
//从processRecord中移除
if (rl.app != null) {
rl.app.receivers.remove(rl);
}
//从mRegisteredReceivers和mReceiverResolver移除
removeReceiverLocked(rl);
if (rl.linkedToDeath) {
rl.linkedToDeath = false;
rl.receiver.asBinder().unlinkToDeath(rl, 0);
}
}
}
// If we actually concluded any broadcasts, we might now be able
// to trim the recipients' apps from our working set
if (doTrim) {
trimApplications(OomAdjuster.OOM_ADJ_REASON_FINISH_RECEIVER);
return;
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
void removeReceiverLocked(ReceiverList rl) {
mRegisteredReceivers.remove(rl.receiver.asBinder());
for (int i = rl.size() - 1; i >= 0; i--) {
mReceiverResolver.removeFilter(rl.get(i));
}
}
广播的发送
定位到
的
ContextWrapper
函数。
sendBroadcast
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
}
public void sendBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess(this);
ActivityManager.getService().broadcastIntentWithFeature(mMainThread.getApplicationThread(), getAttributionTag(), intent, resolvedType,null, Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, nul
以上就是Android广播Broadcast的启动流程是什么的详细内容,更多关于Android广播Broadcast的启动流程是什么的资料请关注九品源码其它相关文章!