注册广播接收器

Android系统的广播机制是一种消息订阅/发布机制,因此,使用这种消息驱动模型的第一步便是订阅消息;而对Android应用程序来说,订阅消息其实就是注册广播接收器。在Android的广播机制中,ActivityManagerService扮演着广播中心的角色,负责系统中所有广播的注册和发布操作,因此,Android应用程序注册广播接收器的过程就把是广播接收器注册到ActivityManagerService的过程。Android应用程序是通过调用ContextWrapper类的registerReceiver函数来把广播接收器BroadcastReceiver注册到ActivityManagerService中去的,而ContextWrapper类本身又借助ContextImpl类来注册广播接收器。在Android应用程序框架中,Activity和Service类都继承了ContextWrapper类,因此,我们可以在Activity或者Service的子类中调用registerReceiver函数来注册广播接收器。Activity、Service、ContextWrapper和ContextImpl这四个类的关系:

registerReceiver函数播接收器注册过程的时序图如下:

接下来对registerReceiver注册广播接收器的源码进行详细分析,由于Activity继承于Context类,Context类是一个抽象类,定义了registerReceiver接口函数,因此在Activity的子类中,可以直接调用registerregisterReceiver函数,但是Activity及其父类都没有实现registerReceiver接口函数,在Activity调用registerReceiver来注册广播接收器时,根据Activity类继承关系,会依次调用一遍其父类的registerReceiver函数,父类ContextWrapper对registerReceiver函数实现如下:

@Overridepublic Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {return mBase.registerReceiver(receiver, filter);}@Overridepublic Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,String broadcastPermission, Handler scheduler) {return mBase.registerReceiver(receiver, filter, broadcastPermission,scheduler);}
这里定义了两个registerReceiver重载函数,以上两个函数的实现都是间接调用mBase对象的registerReceiver函数,mBase定义为Context类型,在Context的子类中,ContextImpl类实现了registerReceiver函数。

@Overridepublic Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {return registerReceiver(receiver, filter, null, null);}@Overridepublic Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,String broadcastPermission, Handler scheduler) {return registerReceiverInternal(receiver, filter, broadcastPermission,scheduler, getOuterContext());}
在ContextImpl类中仍然实现了两个registerReceiver函数的重载,但他们都并没有真正实现该函数,而是调用函数registerReceiverInternal函数来完成,registerReceiverInternal函数的定义如下:

private Intent registerReceiverInternal(BroadcastReceiver receiver,IntentFilter filter, String broadcastPermission,Handler scheduler, Context context) {/* broadcastPermission = null   scheduler = null */IIntentReceiver rd = null;if (receiver != null) {if (mPackageInfo != null && context != null) {if (scheduler == null) {//获取应用程序主线程的handle对象scheduler = mMainThread.getHandler();}//获取IIntentReceiver广播接收分发器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 {/* ActivityManagerNative.getDefault()得到ActivityManagerService在客户进程的代理类对象ActivityManagerProxy,通过Binder进程间通信,远程调用ActivityManagerService的registerReceiver函数 */return ActivityManagerNative.getDefault().registerReceiver(mMainThread.getApplicationThread(), mBasePackageName,rd, filter, broadcastPermission);} catch (RemoteException e) {return null;}}

获取Activity的上下文

final Context getOuterContext() {return mOuterContext;}ContextImpl() { mOuterContext = this;}
由于ContextImpl类为Activity的父类,因此getOuterContext()函数得到的是注册广播接收器的Activity的上下文。

获取应用程序主线程的消息分发器handle

mMainThread.getHandler()

frameworks\base\core\java\android\app\ActivityThread.java

final Handler getHandler() {return mH;}final H mH = new H();private class H extends Handler {public static final int LAUNCH_ACTIVITY         = 100;public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {case LAUNCH_ACTIVITY: {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");ActivityClientRecord r = (ActivityClientRecord)msg.obj;r.packageInfo = getPackageInfoNoCheck(r.activityInfo.applicationInfo, r.compatInfo);handleLaunchActivity(r, null);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);} break;}}}
该handle是在ActivityThread类中定义,用于处理应用程序主线程的消息分发处理。

获取广播接收分发器

frameworks\base\core\java\android\app\LoadedApk.java

public IIntentReceiver getReceiverDispatcher(BroadcastReceiver r,Context context, Handler handler,Instrumentation instrumentation, boolean registered) {synchronized (mReceivers) {LoadedApk.ReceiverDispatcher rd = null;HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = null;//注册广播接收器if (registered) {//以注册广播接收器的Activity为key从mReceivers的Hashmap表中取出该上下文对应的广播接收器表map = mReceivers.get(context);//根据BroadcastReceiver从广播接收器表中取出对应的LoadedApk.ReceiverDispatcherif (map != null) {rd = map.get(r);}}//如果表中不存在,直接创建ReceiverDispatcher对象if (rd == null) {rd = new ReceiverDispatcher(r, context, handler,instrumentation, registered);//并且以<BroadcastReceiver,LoadedApk.ReceiverDispatcher>为键值对的形式保存if (registered) {if (map == null) {map = new HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();mReceivers.put(context, map);}map.put(r, rd);}} else {rd.validate(context, handler);}rd.mForgotten = false;//取得ReceiverDispatcher对象的成员变量mIIntentReceiverreturn rd.getIIntentReceiver();}}
注册的广播接收器的存储方式如下:

LoadedApk.mReceivers


该广播接收器表保存在LoadedApk对象的成员变量mReceivers中。

IIntentReceiver getIIntentReceiver() {return mIIntentReceiver;}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();}InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) { mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd); mStrongRef = strong ? rd : null;}

ActivityManagerProxy注册广播接收器

public Intent registerReceiver(IApplicationThread caller, String packageName,IIntentReceiver receiver,IntentFilter filter, String perm) throws RemoteException{Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IActivityManager.descriptor);data.writeStrongBinder(caller != null ? caller.asBinder() : null);data.writeString(packageName);data.writeStrongBinder(receiver != null ? receiver.asBinder() : null);filter.writeToParcel(data, 0);data.writeString(perm);mRemote.transact(REGISTER_RECEIVER_TRANSACTION, data, reply, 0);reply.readException();Intent intent = null;int haveIntent = reply.readInt();if (haveIntent != 0) {intent = Intent.CREATOR.createFromParcel(reply);}reply.recycle();data.recycle();return intent;}

ActivityManagerProxy通过Binder驱动程序远程调用服务进程的ActivityManagerService的registerReceiver函数来注册广播接收器。

ActivityManagerService注册广播接收器

关于广播接收器的数据结构图:

public Intent registerReceiver(IApplicationThread caller, String callerPackage,IIntentReceiver receiver, IntentFilter filter, String permission) {enforceNotIsolatedCaller("registerReceiver");synchronized(this) {ProcessRecord callerApp = null;if (caller != null) {//caller = mMainThread.getApplicationThread()//获取应用程序的ProcessRecordcallerApp = 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 != Process.SYSTEM_UID &&!callerApp.pkgList.contains(callerPackage)) {throw new SecurityException("Given caller package " + callerPackage+ " is not running in process " + callerApp);}} else {callerPackage = null;}List allSticky = null;// Look for any matching sticky broadcasts...Iterator actions = filter.actionsIterator();if (actions != null) {while (actions.hasNext()) {String action = (String)actions.next();allSticky = getStickiesLocked(action, filter, allSticky);}} else {allSticky = getStickiesLocked(null, filter, allSticky);}// The first sticky in the list is returned directly back to// the client.Intent sticky = allSticky != null ? (Intent)allSticky.get(0) : null;if (receiver == null) {return sticky;}        //从mRegisteredReceivers表中取出receiver对应的ReceiverList,ReceiverList列表用于保存BroadcastFilterReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());if (rl == null) {//创建ReceiverList对象rl = new ReceiverList(this, callerApp,Binder.getCallingPid(),Binder.getCallingUid(), receiver);if (rl.app != null) {//保存到ProcessRecord的receivers成员变量中rl.app.receivers.add(rl);} else {try {receiver.asBinder().linkToDeath(rl, 0);} catch (RemoteException e) {return sticky;}rl.linkedToDeath = true;}//注册到mRegisteredReceivers HashMap表中mRegisteredReceivers.put(receiver.asBinder(), rl);}//根据IntentFilter创建广播接收过滤器BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission);//为当前广播接收器设置Action过滤器rl.add(bf);if (!bf.debugCheck()) {Slog.w(TAG, "==> For Dynamic broadast");}mReceiverResolver.addFilter(bf);// Enqueue broadcasts for all existing stickies that match// this filter.if (allSticky != null) {ArrayList receivers = new ArrayList();receivers.add(bf);int N = allSticky.size();for (int i=0; i<N; i++) {Intent intent = (Intent)allSticky.get(i);BroadcastQueue queue = broadcastQueueForIntent(intent);BroadcastRecord r = new BroadcastRecord(queue, intent, null,null, -1, -1, null, receivers, null, 0, null, null,false, true, true);queue.enqueueParallelBroadcastLocked(r);queue.scheduleBroadcastsLocked();}}return sticky;}}

在ActivityManagerService中,用一个进程记录块来表示这个应用程序进程,它里面有一个列表receivers,专门用来保存这个进程注册的广播接收器。接着,又把这个ReceiverList列表以receiver为Key值保存在ActivityManagerService的成员变量mRegisteredReceivers中。创建BroadcastFilter来把广播接收器列表rl和filter关联起来,然后保存在ActivityManagerService中的成员变量mReceiverResolver中去。

注消广播接收器

frameworks\base\core\java\android\content\ContextWrapper.java

public void unregisterReceiver(BroadcastReceiver receiver) {mBase.unregisterReceiver(receiver);}
frameworks\base\core\java\android\app\ContextImpl.java

public void unregisterReceiver(BroadcastReceiver receiver) {if (mPackageInfo != null) {IIntentReceiver rd = mPackageInfo.forgetReceiverDispatcher(getOuterContext(), receiver);try {ActivityManagerNative.getDefault().unregisterReceiver(rd);} catch (RemoteException e) {}} else {throw new RuntimeException("Not supported in system context");}}
函数首先从表中查找指定广播接收器的IIntentReceiver

public IIntentReceiver forgetReceiverDispatcher(Context context,BroadcastReceiver r) {synchronized (mReceivers) {//从mReceivers表中取出对应的广播接收器表HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> map = mReceivers.get(context);LoadedApk.ReceiverDispatcher rd = null;if (map != null) {//从广播接收器表中取出指定的广播接收器的分发器rd = map.get(r);if (rd != null) {map.remove(r);if (map.size() == 0) {mReceivers.remove(context);}if (r.getDebugUnregister()) {HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder= mUnregisteredReceivers.get(context);if (holder == null) {holder = new HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>();mUnregisteredReceivers.put(context, holder);}RuntimeException ex = new IllegalArgumentException("Originally unregistered here:");ex.fillInStackTrace();rd.setUnregisterLocation(ex);holder.put(r, rd);}//返回ReceiverDispatcher的IntentReceiverrd.mForgotten = true;return rd.getIIntentReceiver();}}HashMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher> holder= mUnregisteredReceivers.get(context);if (holder != null) {rd = holder.get(r);if (rd != null) {RuntimeException ex = rd.getUnregisterLocation();throw new IllegalArgumentException("Unregistering Receiver " + r+ " that was already unregistered", ex);}}if (context == null) {throw new IllegalStateException("Unbinding Receiver " + r+ " from Context that is no longer in use: " + context);} else {throw new IllegalArgumentException("Receiver not registered: " + r);}}}
通过ActivityManagerProxy代理向ActivityManagerService发送注销广播接收器的请求

public void unregisterReceiver(IIntentReceiver receiver) throws RemoteException{Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInterfaceToken(IActivityManager.descriptor);data.writeStrongBinder(receiver.asBinder());mRemote.transact(UNREGISTER_RECEIVER_TRANSACTION, data, reply, 0);reply.readException();data.recycle();reply.recycle();} 
ActivityManagerService负责广播接收器的注销工作:

public void unregisterReceiver(IIntentReceiver receiver) {if (DEBUG_BROADCAST) Slog.v(TAG, "Unregister receiver: " + receiver);final long origId = Binder.clearCallingIdentity();try {boolean doTrim = false;synchronized(this) {//从mRegisteredReceivers表中查找到receiver对应的ReceiverListReceiverList rl = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder());if (rl != null) {if (rl.curBroadcast != null) {BroadcastRecord r = rl.curBroadcast;final boolean doNext = finishReceiverLocked(receiver.asBinder(), r.resultCode, r.resultData,r.resultExtras, r.resultAbort, true);if (doNext) {doTrim = true;r.queue.processNextBroadcast(false);}}if (rl.app != null) {//从应用进程的receivers表中移除当前广播接收器对应的ReceiverListrl.app.receivers.remove(rl);}//从mRegisteredReceivers表中移除receiver,同时从mReceiverResolver的过滤ActionremoveReceiverLocked(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 setif (doTrim) {trimApplications();return;}} finally {Binder.restoreCallingIdentity(origId);}}
至此广播接收器的注册与注销就介绍完了,注册的本质其实就是将广播接收器添加到ActivityManagerService的相应成员变量中存储,从而在分发广播的时候,可以根据表中注册的接收器来分发;而广播接收器的注销工作就是从相应的存储表中移除。

更多相关文章

  1. 箭头函数的基础使用
  2. Python技巧匿名函数、回调函数和高阶函数
  3. 浅析android通过jni控制service服务程序的简易流程
  4. Android四大基本组件介绍与生命周期
  5. Android(安卓)bluetooth介绍(四): a2dp connect流程分析
  6. 第三章 Android程序设计基础
  7. Android架构分析之使用自定义硬件抽象层(HAL)模块
  8. Android中OpenMax的适配层
  9. android 包管理系统分析

随机推荐

  1. Android图形报表之AchartEngine(附开发包
  2. Android中设定EditText的输入长度
  3. android TextView属性详解
  4. Android(安卓)自定义渐变背景
  5. Android(安卓)命令行手动编译打包详解
  6. Android应用程序组件Content Provider在
  7. Android(安卓)Asynchronous HTTPClient t
  8. android 横向滚动屏幕实现(3)
  9. 更改android spinner 背景
  10. Android(安卓)SearchView介绍及搜索提示