- 浏览: 961904 次
文章分类
最新评论
-
l67721363:
感谢分享,要是有各个函数性能比较就好了。
SQL优化 数据库优化 -
hanmiao:
此图片来自QQ空间,未经允许不可引用。
Hacking QQ空间
Android 广播接收器注册与注销源码分析
注册广播接收器
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函数实现如下:
@Override public Intent registerReceiver( BroadcastReceiver receiver, IntentFilter filter) { return mBase.registerReceiver(receiver, filter); } @Override public 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函数。
@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, 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.ReceiverDispatcher if (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对象的成员变量mIIntentReceiver return 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() //获取应用程序的ProcessRecord callerApp = 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列表用于保存BroadcastFilter ReceiverList 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的IntentReceiver rd.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对应的ReceiverList ReceiverList 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表中移除当前广播接收器对应的ReceiverList rl.app.receivers.remove(rl); } //从mRegisteredReceivers表中移除receiver,同时从mReceiverResolver的过滤Action 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(); return; } } finally { Binder.restoreCallingIdentity(origId); } }至此广播接收器的注册与注销就介绍完了,注册的本质其实就是将广播接收器添加到ActivityManagerService的相应成员变量中存储,从而在分发广播的时候,可以根据表中注册的接收器来分发;而广播接收器的注销工作就是从相应的存储表中移除。
相关推荐
Android记住密码,线程自动登录,注销
Android studio成品项目 点菜系统 源码 apk 可以实现登录注册功能,菜品喜欢,联系以及账户充值功能,包括源码以及apk,单机无联网功能,含项目报告。
SQLite数据库 ,实现本地、登录、注册、 修改、注销账号、记住密码
Android studio源码,记事本,可做备忘录 纯安卓项目本地数据库sqlite 功能:登陆注册 增删改 注销 项目包含 源码+apk文件+演示视频 温馨提示~ 由于项目具有复制性,售出不退,不包售后 项目直接导入即可运行,推荐...
Android APP实现QQ登录、注销、QQ分享,获取QQ用户信息修改QQ头像等。有volley网络框架使用和Glide使用网络加载图片,华为推送消息功能。
资源介绍:。注册和注销控件注册易语言模块源码。资源作者:。易语言入门自学。资源界面:。资源下载:。
9.2 广播接收者的注册过程 9.3 广播的发送过程 第10章 Content Provider组件的实现原理 10.1 Content Provider组件应用实例 10.1.1 ArticlesProvider 10.1.2 Article 10.2 Content Provider组件的启动过程 ...
能够实现一键锁屏,android注销,当用户需要注销时,此代码就能实现更换用户功能
wince下注册控件源码,evc4.0编写,工程中包括 arm4和mips系列的编译选项。直接用打开对话框选择控件,然后进行注册或注销即可
Android安卓IOS苹果window电脑网游手游游戏加速器系统全套定制开发客户端源码
基于C++对exosip的封装,集成了以下功能: 1、sip注册; 2、sip呼叫; 3、sip接听; 4、sip注销; 5、sip事件消息回调; 6、sip底层sdp回调; 7、sip底层message发送及回调;
9.2 广播接收者的注册过程 9.3 广播的发送过程 第10章 Content Provider组件的实现原理 10.1 Content Provider组件应用实例 10.1.1 ArticlesProvider 10.1.2 Article 10.2 Content Provider组件的启动...
map reduce的全部执行流程,源码分析视图
Android studio 运动健康管理系统源码.zip
Python基于Frida的Android App隐私合规检测辅助工具源码.zip
用android studio实现的记账本app,有登录注册界面,可以实现消费的记录的增加与删除。
Android核心技术与实例详解 随书源码 原书地址:http://download.csdn.net/detail/su_xiaoyan/7976991
android之利用SQLite数据库实现登陆和注册,使用SQLiteOpenHelper抽象类建立数据库,建立数据库类DatabaseHelper,写业务类实现查询和插入
基于Android开发的图书管理系统,实现注册,登录,课程热门、分类查询,课程购买,充值,评论。