Broadcast流程1--注册广播
来源:互联网 发布:手机数据连接上不了网 编辑:程序博客网 时间:2024/05/17 03:08
1. 广播类型:
普通广播:通过Context.sendBroadcast()发送,可并行处理
有序广播:通过Context.sendOrderedBroadcast()发送,串行处理
Sticky广播:通过Context.sendStickyBroadcast()发送,黏性广播,本文不分析
2.广播注册方式:
动态注册:在Activity中通过registerReceiver和unRegisterReceiver方法
静态注册:在AndroidManifest.xml文件中配置
3.动态注册广播流程
activity中registerReceiver,其实就是调用ContextImpl.java的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, getUserId(), filter, broadcastPermission, scheduler, getOuterContext()); }
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(); } //mPackageInfo是LoadedApk。 //在Android的架构里,应用进程里是用LoadedApk来对应一个apk的。进程里加载了多少个apk,就会有多少LoadedApk。每个LoadedApk里会有一张“关于本apk动态注册的所有receiver”的哈希表(mReceivers)。 //查找和context对应的“子哈希表”里的ReceiverDispatcher,如果找不到,就重新new一个 *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 = ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId); if (intent != null) { intent.setExtrasClassLoader(getClassLoader()); intent.prepareToEnterProcess(); } return intent; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); }}
上面最重要的就是获得一个实现IIntentReceiver 接口的对象,最后将这个对象注册到AMS中
如图所示,拥有IIntentReceiver 接口的对象,跟BroadcastReceiver对象一一对应,
其实就相当于BroadcastReceiver对象的中间步骤的映射,但是能够跨进程。
下图是引用品茗论道说广播 悠然红茶的
https://my.oschina.net/youranhongcha/blog/226274的图片,非常经典的图片,显示了动态注册的过程
在AMS中的方法:
public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId) { enforceNotIsolatedCaller("registerReceiver"); ArrayList<Intent> stickyIntents = null; ProcessRecord callerApp = null; int callingUid; int callingPid; synchronized(this) { if (caller != null) { //获取注册广播的activity所对应的进程 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.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(); } userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true, ALLOW_FULL_ONLY, "registerReceiver", callerPackage); Iterator<String> actions = filter.actionsIterator(); if (actions == null) { ArrayList<String> noAction = new ArrayList<String>(1); noAction.add(null); actions = noAction.iterator(); } ... synchronized (this) { if (callerApp != null && (callerApp.thread == null || callerApp.thread.asBinder() != caller.asBinder())) { // Original caller already died return null; } //这句最重要,就是为了获取IIntentReceiver 接口是否在AMS中存在ReceiverList,也就是在 //寻找,在AMS中是否存在对应的动态注册的广播接受者(如果是之前就动态注册过,应该存在AMS中名单中) //这个ReceiverList的作用是一个映射,关于BroadcastReceiver和IntentFilter的映射关系 //在一个activity中,一个BroadcastReceiver可以接受几个IntentFilter的过滤条件 ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (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; } //新建立的ReceiverList(代表BroadcastReceiver),放入AMS中已经注册的mRegisteredReceivers //(相当于在AMS中动态注册的所有BroadcastReceiver),这个是注册的角度的变量,用来通过这个寻找广播的接收者。 mRegisteredReceivers.put(receiver.asBinder(), rl); } else if (rl.uid != callingUid) { throw new IllegalArgumentException( "Receiver requested to register for uid " + callingUid + " was previously registered for uid " + rl.uid); } else if (rl.pid != callingPid) { throw new IllegalArgumentException( "Receiver requested to register for pid " + callingPid + " was previously registered for pid " + rl.pid); } else if (rl.userId != userId) { throw new IllegalArgumentException( "Receiver requested to register for user " + userId + " was previously registered for user " + rl.userId); } BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId); rl.add(bf); if (!bf.debugCheck()) { Slog.w(TAG, "==> For Dynamic broadcast"); } //mReceiverResolver这个从解析广播的角度考虑的,用来解析BroadcastRecord。 //作用是AMS将广播队列中的广播寻找到对应的BroadcastFilter , //通过这个BroadcastFilter 再回朔ReceiverList,然后找到BroadcastReceiver。 mReceiverResolver.addFilter(bf); }
阅读全文
0 0
- Broadcast流程1--注册广播
- Android Broadcast广播注册和发布方式以及机制流程
- 广播broadcast常识1
- 广播broadcast动态注册【能调用】
- 广播broadcast静态注册【可调用】
- Android Studio:Broadcast 静态&动态广播注册
- Android---广播(Broadcast)---广播接收者的注册过程分析
- 系统BroadCast的注册发送流程
- Android系统广播(1)–动态注册流程
- broadcast广播
- Broadcast广播
- broadcast 广播
- Broadcast广播
- broadcast广播
- Broadcast广播
- 广播 (Broadcast)
- 广播Broadcast
- Broadcast广播
- LL(1)分析法(简单版)_C++实现
- Linux下搭建ftp服务
- 英语标点符号及翻译
- mybatis防止sql注入
- 数据保存时,出现‘record not found or changed by another user’错误信息的解决办法
- Broadcast流程1--注册广播
- python黑帽子之netcat(chapter1)
- org.apache.http不存在或找不到,解决方案
- pollard's rho算法(使用GMP库)
- 精通CSS(4.4opacity&RGBa)&&黑客与画家(2)
- 【Oracle】单行函数
- 欢迎使用CSDN-markdown编辑器
- 岛屿的数量(思维)
- js 正则