BroadcastReceiver源码分析系列(一):注册广播
来源:互联网 发布:文心雕龙数据库有吗 编辑:程序博客网 时间:2024/05/21 07:57
BroadcastReceiver源码分析系列(一):注册广播
BroadcastReceiver是Android组件中最基本也是最为常见用的四大组件之一,分析BroadcastReceiver相关流以及源码可以加深对BroadcastReceiver的了解。本文先分析注册广播有点内容。
注册类型
注册广播分为静态注册和动态注册
静态注册
- 静态注册是在AndroidManifest中注册,根据需求填写不同的intent-filter,接收相应匹配规则的广播,代码如下
- intent-filter的匹配规则可见博主之前的Android隐式启动intent-filter详解
... <receiver android:name=".xxx.xxxReceiver"> <intent-filter> <action android:name="xxx"/> </intent-filter> </receiver> ...
- 静态注册是在应用安装或开机重启时被解析并注册
动态注册
- 动态注册代码如下
BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (TextUtils.isEmpty(action)) { Log.d(TAG, "onReceive: " + action); } } }; private void f(){ IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("xxx"); registerReceiver(receiver, intentFilter) }
- registerReceiver的具体实现在ContextImpl,最终调用到registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) - registerReceiverInternal首先根据当前BroadcastReceiver创建(获取)一个IIntentReceiver对象,IIntentReceiver是一个Binder接口可以在进程间传递。接着调用ActivityManagerNative.getDefault().registerReceiver,其实就是Binder调用AMS registerReceiver。
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(); } // 第一步获取IIntentReceiver,mPackageInfo是LoadedApk rd = mPackageInfo.getReceiverDispatcher( receiver, context, scheduler, mMainThread.getInstrumentation(), true); } ... } try { // 第二步,调用AMS的registerReceiver final Intent intent = ActivityManagerNative.getDefault().registerReceiver( mMainThread.getApplicationThread(), mBasePackageName, rd, filter, broadcastPermission, userId); return intent; } ... }
LoadedApk
Local state maintained about a currently loaded .apk.
LoadedApk对象是APK文件在内存中的表示。 Apk文件的相关信息,诸如Apk文件的代码和资源,甚至代码里面的Activity,Service、Receiver等组件的信息我们都可以通过此对象获取。
- 第一步调用LoadedApk的getReceiverDispatcher,将BroadcastReceiver转化为能在进程间传递的Binder接口——IIntentReceiver,因为BroadcastReceiver的注册是跨进程的。
- IIntentReceiver的实现类是ReceiverDispatcher.InnerReceiver,ReceiverDispatcher里面保存了当前的BroadcastReceiver和相应的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) { // private final ArrayMap<Context, // ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mServices // 根据当前的Context获取ArrayMap<BroadcastReceiver, // LoadedApk.ReceiverDispatcher> map = mReceivers.get(context); if (map != null) { // 如果存在,尝试根据当前的BroadcastReceiver获取ReceiverDispatcher rd = map.get(r); } } if (rd == null) { // 如果与BroadcastReceiver对应的ReceiverDispatcher不存在,创建一个保存了当前BroadcastReceiver的ReceiverDispatcher对象, // 并将之前传入的主线的Handle保存,同时创建一个InnerReceiver对象保存 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 { // 如果最开始就获取到ReceiverDispatcher,比如多次registerReceiver, // 就会调用ReceiverDispatcher的validate判断此次registerReceiver是否合法 // validate的判断逻辑比较简单,1.判断当前的context是否和之前registerReceiver的一样 2.判断当前handler是否是主线程的handle // 以上两个条件都满足的情况下正常执行,反之抛出相应的异常 rd.validate(context, handler); } rd.mForgotten = false; return rd.getIIntentReceiver(); } }
ActivityManagerService
public abstract class ActivityManagerNative extends Binder implements IActivityManager
public interface IActivityManager extends IInterface
从中可以看出ActivityManagerNative是一个Binder类,Activity的启动已经通过Binder调用转交到系统服务中了。
IActivityManager Binder具体实现是ActivityManagerService,最终调用到ActivityManagerService的registerReceiver
调用进入ActivityManagerService的进程
- ActivityManagerService的registerReceiver,registerReceiver将当前的IIntentReceiver当做KEY,将ReceiverList当做VALUE,保存在mRegisteredReceivers中。
将广播的filter保存在之前的ReceiverList和mReceiverResolver中,代码如下
public Intent registerReceiver(IApplicationThread caller, String callerPackage, IIntentReceiver receiver, IntentFilter filter, String permission, int userId) { ... synchronized (this) { ... // 创建ReceiverList 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); } // HashMap<IBinder, ReceiverList> mRegisteredReceivers // 将IIntentReceiver=KEY,ReceiverList=VALUE,保存在mRegisteredReceivers mRegisteredReceivers.put(receiver.asBinder(), rl); } BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId); // ReceiverList保存Filter // ReceiverList extends ArrayList<BroadcastFilter>,可以添加多个Filter rl.add(bf); // mReceiverResolver保存Filter mReceiverResolver.addFilter(bf); ... return sticky; } }
结论
流程图待补充
阅读全文
0 0
- BroadcastReceiver源码分析系列(一):注册广播
- BroadcastReceiver源码分析系列(二):发送和接收广播
- Android广播之注册广播(包括静态广播和动态广播的注册)源码分析
- 动态广播注册源码分析
- 注册广播BroadcastReceiver
- BroadcastReceiver注册、发送、接收源码分析
- BroadcastReceiver(一)在AndroidManifest.xml中配置的广播接收器(自动注册注销)
- BroadcastReceiver广播静态注册细节
- 广播接收器(BroadcastReceiver)的分析
- BroadcastReceiver广播接收者(一)——利用代码注册广播接收者
- Android广播注册机制剖析【android广播系列一】
- 源码阅读--BroadcastReceiver广播机制
- Android4.4 Framework分析——广播的注册(BroadcastReceiver)和发送(sendbroadcast)过程分析
- BroadcastReceiver静态注册广播与动态注册广播接收器
- Android源码解析四大组件系列(五)---广播的注册过程
- Android 广播接收器BroadcastReceiver(一)
- BroadcastReceiver register 广播的动态注册方式
- Android静态注册内部类广播BroadcastReceiver
- POI2005 泛做
- 最小生成树---Kruskal算法
- RIP协议
- 在linux上安装redis
- C++ 单例模式 释放资源 析构函数的应用
- BroadcastReceiver源码分析系列(一):注册广播
- chrome浏览器保存mht网页文件的方法
- Redhalt6网络设置,图形界面和命令行模式
- delayqueue
- 从物理内存角度描述内存之间的关系(bootmem_init)
- Rust: Operations with sequence
- LeetCode230. Kth Smallest Element in a BST
- Struts2:一
- Mysql架构组成之存储引擎总结