BroadCastReceiver- 工作流程

一:广播注册过程

注册过程

注册过程补充

1. ContextImpl.registerReceiverInternal():
(1) 获得一个ItentReceiver对象,用来进行Binder通信。
(2) 通过ActivityManagerProxy来进行跨进程注册广播。

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();
               }
               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 {
           return ActivityManagerNative.getDefault().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName,
                   rd, filter, broadcastPermission, userId);
       } catch (RemoteException e) {
           return null;
           }
    }

2. LoadApk.getReceiverDispatcher():
1 获得LoadApk.ReceiverDispacher. IIntentReceiver对象,IIntentReceiver对象 是一个Binder对象,可以用来跨进程传输。
2 BroadCastReceiver是系统组件,不能跨进程传输,所以用IIntentReceiver来进行代替BroadCastReceiver来进行跨进程传输。
3 map里面存储的是 <BroadcastReceiver, LoadedApk.ReceiverDispatcher>键值对,用来做缓存。

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) {
                 map = mReceivers.get(context);
               if (map != null) {
                    rd = map.get(r);
                }
             }
             if (rd == null) {
                 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 {
                rd.validate(context, handler);
           }
             rd.mForgotten = false;
            return rd.getIIntentReceiver();
        }
    }

3. LoadApk.ReceiverDispatcher.InnerReceiver:是IIntentReceiver.Stub的实现类.是Binder对象

final static class InnerReceiver extends IIntentReceiver.Stub {
           final WeakReference<LoadedApk.ReceiverDispatcher> mDispatcher;
           final LoadedApk.ReceiverDispatcher mStrongRef;

            InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
                mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                 mStrongRef = strong ? rd : null;
             }
            public void performReceive(Intent intent, int resultCode, String data,
                     Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                LoadedApk.ReceiverDispatcher rd = mDispatcher.get();
               if (ActivityThread.DEBUG_BROADCAST) {
                    int seq = intent.getIntExtra("seq", -1);
                    Slog.i(ActivityThread.TAG, "Receiving broadcast " + intent.getAction() + " seq=" + seq
                             + " to " + (rd != null ? rd.mReceiver : null));
                }
                if (rd != null) {
                   rd.performReceive(intent, resultCode, data, extras,
                             ordered, sticky, sendingUser);
                 } else {
                    // The activity manager dispatched a broadcast to a registered
                     // receiver in this process, but before it could be delivered the
                    // receiver was unregistered.  Acknowledge the broadcast on its
                     // behalf so that the system's broadcast sequence can continue.
                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing broadcast to unregistered receiver");
                     IActivityManager mgr = ActivityManagerNative.getDefault();
                     try {
                         if (extras != null) {
                           extras.setAllowFds(false);
                         }
                        mgr.finishReceiver(this, resultCode, data, extras, false);
                     } catch (RemoteException e) {
                       Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
                     }
                 }
            }
        }

二:广播的发送和接收过程

广播的发送和接收过程

三:广播工作过程细致分析

(1)BroadcastReceiver和广播的匹配过程

在broadcastIntentLocked方法内部有如下代码:

// Figure out who all will receive this broadcast.
List receivers = null;
List<BroadcastFilter> registeredReceivers = null;
// Need to resolve the intent to interested receivers...
if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY)
         == 0) {
    receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
}
if (intent.getComponent() == null) {
    if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) {
        // Query one target user at a time, excluding shell-restricted users
        // 略
    } else {
        registeredReceivers = mReceiverResolver.queryIntent(intent,
                resolvedType, false, userId);
    }
}
receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false, userId);

receivers:是对这个广播感兴趣的静态BroadcastReceiver列表
mReceiverResolver:存储了动态注册的BroadcastReceiver的信息;通过mReceiverResolver.qureyIntent匹配出了对应的BroadcastReceiver供进一步使用。

(2)接收过程

broadcastIntentLocked方法的后半部分有如下代码
1 首先创建了一个BroadcastRecord代表此次发送的这条广播,然后把它丢进一个队列,最后通过scheduleBroadcastsLocked通知队列对广播进行处理。


BroadcastQueue queue = broadcastQueueForIntent(intent);
BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
        callerPackage, callingPid, callingUid, resolvedType,
        requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
        resultData, resultExtras, ordered, sticky, false, userId);

boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
if (!replaced) {
    queue.enqueueOrderedBroadcastLocked(r);
    queue.scheduleBroadcastsLocked();
}

BroadcastQueue.scheduleBroadcastsLocked()
在BroadcastQueue中通过Handler调度了对于广播处理的消息,调度过程由processNextBroadcast方法完成。

public void scheduleBroadcastsLocked() {
       if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts ["
                 + mQueueName + "]: current="
               + mBroadcastsScheduled);

       if (mBroadcastsScheduled) {
            return;
         }
         mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));
         mBroadcastsScheduled = true;
     }
}

BroadcastQueue.processNextBroadcast():这个方法通过performReceiveLocked最终调用了IIntentReceiver的performReceive方法。

private final class BroadcastHandler extends Handler {
         public BroadcastHandler(Looper looper) {
             super(looper, null, true);
         }
 
        @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
                case BROADCAST_INTENT_MSG: {
                    if (DEBUG_BROADCAST) Slog.v(
                             TAG, "Received BROADCAST_INTENT_MSG");
                     processNextBroadcast(true);
                } break;
                 case BROADCAST_TIMEOUT_MSG: {
                     synchronized (mService) {
                        broadcastTimeoutLocked(true);
                     }
               } break;
             }
        }
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,294评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,780评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,001评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,593评论 1 289
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,687评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,679评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,667评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,426评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,872评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,180评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,346评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,019评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,658评论 3 323
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,268评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,495评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,275评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,207评论 2 352

推荐阅读更多精彩内容