企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
#### 9.4.1 广播的注册过程 广播的注册分为静态注册和动态注册,其中静态注册的广播在应用安装时由系统自动完成注册,具体来说是由PMS(PackageManagerService)来完成整个注册过程的,除了广播以外,其他三大组件也都是在应用安装时由PMS解析并注册的。这里只分析广播的动态注册的过程,动态注册的过程是从ContextWrapper的registerReceiver方法开始的,和Activity以及Service一样。ContextWrapper并没有做实际的工作,而是将注册过程直接交给了ContextImpl来完成,如下所示。 public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); } ContextImpl的registerReceiver方法调用了自己的registerReceiverInternal方法,它的实现如下所示。 private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId, IntentFilter filter, String broadcastPermission, Handler scheduler, Context context) { 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).getIIntent- Receiver(); } } try { return ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId); } catch (RemoteException e) { return null; } } 在上面的代码中,系统首先从mPackageInfo获取IIntentReceiver对象,然后再采用跨进程的方式向AMS发送广播注册的请求。之所以采用IIntentReceiver而不是直接采用BroadcastReceiver,这是因为上述注册过程是一个进程间通信的过程,而BroadcastReceiver作为Android的一个组件是不能直接跨进程传递的,所以需要通过IIntentReceiver来中转一下。毫无疑问,IIntentReceiver必须是一个Binder接口,它的具体实现是LoadedApk.Receiver-Dispatcher.InnerReceiver, ReceiverDispatcher的内部同时保存了BroadcastReceiver和InnerReceiver,这样当接收到广播时,ReceiverDispatcher可以很方便地调用BroadcastReceiver的onReceive方法,具体会在9.4.2节中说明。可以发现,BroadcastReceiver的这个过程和Service的实现原理类似,Service也有一个叫ServiceDispatcher的类,并且其内部类InnerConnection也是一个Binder接口,作用同样也是为了进程间通信,这一点在9.3.2节中已经描述过了,这里不再重复说明。 关于ActivityManagerNative.getDefault(),这里就不用再做说明了,它就是AMS,在前面的章节中已经多次提到它。下面看一下ReceiverDispatcher的getIIntentReceiver的实现,如下所示。很显然,getReceiverDispatcher方法重新创建了一个ReceiverDispatcher对象并将其保存的InnerReceiver对象作为返回值返回,其中InnerReceiver对象和BroadcastReceiver都是在ReceiverDispatcher的构造方法中被保存起来的。 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(); } } 由于注册广播的真正实现过程是在AMS中,因此我们需要看一下AMS的具体实现。AMS的registerReceiver方法看起来很长,其实关键点就只有下面一部分,最终会把远程的InnerReceiver对象以及IntentFilter对象存储起来,这样整个广播的注册过程就完成了,代码如下所示。 public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId) { ... mRegisteredReceivers.put(receiver.asBinder(), rl); BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId); rl.add(bf); if (! bf.debugCheck()) { Slog.w(TAG, "==> For Dynamic broadast"); } mReceiverResolver.addFilter(bf); ... }