BroadcastReceiver 工作流程源码解析

BroadcastReceiver 注册过程

  • 静态注册:程序安装时由 PackageManagerService 即 PMS 解析并完成注册,与 Activity Service ContentProvider 注册相同。

  • 动态注册从 ContextImpl 的 registReceiver 方法开始,调用 registReceiverInternal 方法

应用进程

注册过程需要将 Receiver 传递,注册过程是一个跨进程通信,需要使用跨进程方式向 AMS 提交注册请求,BroadcastReceiver 是一个组件是不可以直接传递的,IIntentReceiver 是一个 Binder,可以使用 IIntentReceiver 来中转

BroadcastReceiver 不可以跨进程传输,registReceiverInternal 方法会从 LoadedApk 中将 BroadcastReceiver 转化为 IIntentReceiver ,IIntentReceiver 的具体实现是 LoadedApk 中的内部类 ReceiverDispatcher 的内部类 InnerReceiver。转化过程同绑定形式的 Service 中 ServiceConnection 的转化,InnerReceiver 为 AIDL 中的 Stub,跨进程后会在系统进程由 Stub 得到 Proxy 代理对象,广播的接收过程中并不会调用 Proxy 对象的方法通过 IPC 调用 Stub 对象的方法,而是会在接收时将 Proxy 再传递到应用进程,应用进程根据 Proxy 找到 Stub,再调用 Stub 的方法完成接收

ReceiverDispatcher 中保存了 BroadCastReceier 和 InnerReceiver,这样当接收到广播时,可以很方便的调用 BroadcastReceiver 的 onReceive 方法,InnerReceiver 中持有了 ReceiverDispatcher 的弱引用,通过 ReceiverDispatcher 能拿到其内部存储的 BroadCastReceier 对象,就可以调用 BroadCastReceier 对象的方法。

系统进程

转换后在 registRecieverInternal 中调用 ActivityManagerNative.getDefault().registerReceiver() 方法,即调用 AMS 的 registerReceiver

registerReceiver 中主要是将 InnerReceiver 及 IntentFilter 保存起来,注册过程结束。

BroadcastReceiver 的发送和接收工作过程

应用进程

ContextImpl 中的 sendBroadCast 方法中直接调用 AMS 的 broadcastIntent 方法

系统进程

broadcastIntent 中 调用 broadcastIntentLocked 方法,这个方法中为 broadcast 添加了 FLAG_EXCLUDE_STOPPED_PACKAGES 标记

  • 从 Android 3.1 开始,已经添加了该特性,表示不会将广播发送给已经停止的应用。FLAG_EXCLUDE_STOPPED_PACKAGES 和 FLAG_INCLUDE_STOPPED_PACKAGES 标记位都是 3.1 添加的,第一个表示不会将广播发送给已停止的应用,第二个表示会将广播发送给已停止的应用,两个同时存在,以会发送为准。停止状态包含两种,第一种是安装了但未运行,第二种是应用被强行停止。

broadcastIntent 中,根据 intent 和 intent-filter 查找出匹配的广播接收者并经过一系列条件过滤,最终将满足条件的广播接收者添加到 BroadcastQueue ,接着 BroadcastQueue 就会调用 scheduleBroadcastsLocked 方法将广播发送给相应的接收者

scheduleBroadcastLocked 方法不会直接发送广播,会使用其内部的 Handler 发送一条 Message ,消息内容为 BroadcastQueue 本身,Handler 收到消息后,调用 BroadcastQueue 中的 processNextBroadcast 方法

processNextBroadcast 方法中,无序广播存储在 ArrayList mParalleBroadcast 集合中,while 循环,遍历时总是去除第一个 remove 掉,remove 的返回值为移除的接收者对象,一直到集合长度为 0

循环发送

循环中会调用 deliverToRegisteredReceiverLocked 方法并在该方法内部调用 performReceiveLocked 方法将一个广播发送给接收者

performReceiveLocked 方法中调用 app.thread.scheduleRegisteredReciever() 方法,app.thread 为 IApplicationThread 的实现类 ApplicationThread 的实例。

应用进程

scheduleRegisteredReceiver 方法中会调用 IIntentReciever 的实现类 InnerReceiver 的 performReceiver 方法,并在其内部调用 LoadedApk.ReceiverDispatcher 的 performReceive 方法

performReceive 方法中,会创建一个 Args 对象,Args 实现了Runnable 接口并且是 ReceiverDispatcher 的内部类,并调用主进程的 Handler 也就是 ActivityThread 中的 Handler mH的 post 方法将 args 对象传入,执行 args 的 run 方法。run 方法中调用了 ReceiverDispatcher 中保存的 BroadCastReceiver 的 onReceived 方法,并将发送的广播中的Intent 传递到 onReceive 方法中。并且是在主线程调用的。发送和接收过程也就结束了。

使用 post 的原因,ApplicationThread 是 IApplicationThread 的 Stub 实现类,也是通过 Binder 完成进程间通信的一部分,其执行在 Binder 线程,所以需要通过 ActivityThread 中的 Handler 的 post 方法将执行线程切换到主线程

BroadcastReceiver 注册过程进程转换

应用进程主线程发起注册 --> AMS 系统进程将接收者保存

BroadcastReceiver 发送和接收进程转换

应用进程主线程发起注册 --> AMS 系统进程找到接收者 --> 在 ApplicationThread 中调用 ActivityThread 中的 Handler 处理消息将进程切换到应用进程主线程

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,348评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,122评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,936评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,427评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,467评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,785评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,931评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,696评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,141评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,483评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,625评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,291评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,892评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,492评论 2 348

推荐阅读更多精彩内容