BroadCastReceiver的工作过程

API版本 26
参考资料:Android开发艺术探索

总体流程预览
这里写图片描述

这里写图片描述


在Activity中调用registerReceiver方法,最终调用的是ContextWrapper中的registerReceiver方法。

广播的注册过程

1 ContextWrapper

1.1 registerReceiver

@Override
    public Intent registerReceiver(
        BroadcastReceiver receiver, IntentFilter filter) {
        return mBase.registerReceiver(receiver, filter);
    }

通过上一篇文章中Service的创建过程,可知,此处的mBase对象即为ContextImpl对象。

2 ContextImpl

2.1 registerReceiver

在ContextImpl中最终都是调用的五个参数的registerReceiver的重载方法。

 @Override
    public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
            String broadcastPermission, Handler scheduler, int flags) {
        return registerReceiverInternal(receiver, getUserId(),
                filter, broadcastPermission, scheduler, getOuterContext(), flags);
    }

在方法中,调用了registerReceiverInternal方法。

2.2 registerReceiverInternal

private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission,
            Handler scheduler, Context context, int flags) {
        IIntentReceiver rd = null;
        if (receiver != null) {
            if (mPackageInfo != null && context != null) {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                //1 创建LoadedApk.ReceiverDispatcher对象并在ReceiverDispatcher的构造方法中保存InnerReceiver和BroadcastReceiver对象
                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 {
	        //2  注册广播的真正实现是在AMS的registerReceiver
            final Intent intent = ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                    broadcastPermission, userId, flags);
            if (intent != null) {
                intent.setExtrasClassLoader(getClassLoader());
                intent.prepareToEnterProcess();
            }
            return intent;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

由这段代码中的这一行

rd = mPackageInfo.getReceiverDispatcher(
                    receiver, context, scheduler,
                    mMainThread.getInstrumentation(), true);

结合之前Service的创建过程可知,这里的Binder的接口IIntentReceiver的实现类为LoadedApk.ReceiverDispatcherInnerReceiver。

final static class InnerReceiver extends IIntentReceiver.Stub 

在registerReceiverInternal方法中首先会调用LoadedApk中的getReceiverDispatcher来创建ReceiverDispatcher对象

3 LoadedApk

3.1 getReceiverDispatcher

 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();
        }
    }

可以看到,在上面这段代码中通过下面这段代码直接创建了ReceiverDispatcher。

rd = new ReceiverDispatcher(r, context, handler,
                        instrumentation, registered);

继续追踪ReceiverDispatcher的构造方法可知

3.2 保存InnerReceiver对象

BroadCastReceiver和InnerReceiver对象被保存到ReceiverDispatcher中

 mIIntentReceiver = new InnerReceiver(this, !registered);
 mReceiver = receiver;

在getReceiverDispatcher方法中,最后返回ReceiverDispatcher中保存的InnerReceiver对象。

return rd.getIIntentReceiver();

回过头来接着看ContextImpl中的registerReceiverInternal方法,根据下面这一段可知,将ReceiverDispatcher中的InnerReceiver对象直接保存到了ActivityManagerService中

final Intent intent = ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                    broadcastPermission, userId, flags);

4 ActivityManagerService

4.1 registerReceiver

首先来看AMS中的两个变量
mReceiverResolver:AMS中用来存储IntentFilter的对象

 /**
     * Resolver for broadcast intents to registered receivers.
     * Holds BroadcastFilter (subclass of IntentFilter).
     */
    final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
            = new IntentResolver<BroadcastFilter, BroadcastFilter>()

mRegisteredReceivers:AMS中用来存储InnerReceiver

 /**
     * Keeps track of all IIntentReceivers that have been registered for broadcasts.
     * Hash keys are the receiver IBinder, hash value is a ReceiverList.
     */
    final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
```java
registerReceiver方法很长,下面截取主要代码。

mRegisteredReceivers.put(receiver.asBinder(), rl);

```java
BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
mRegisteredReceivers.put(receiver.asBinder(), rl);

通过上面两行代码,把远程的InnerReceiver对象以及IntentFilter对象存储起来。

广播的发送和接收过程

和之前一样,在Activity中调用registerReceiver方法,最终调用的是ContextWrapper中的sendBroadcast方法。

1 ContextWrapper

1.1 sendBroadcast

@Override
    public void sendBroadcast(Intent intent) {
        mBase.sendBroadcast(intent);
    }

在ContextWrapper依然什么都没做,转交给了ContextImpl去处理。

2 ContextImpl

2.1 sendBroadcast

 @Override
    public void sendBroadcast(Intent intent) {
        warnIfCallingFromSystemProcess();
        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
        try {
            intent.prepareToLeaveProcess(this);
            ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                    getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

从上面这段代码可知,ContextImpl也是几乎什么都没干,直接又转交给了AMS,下面是AMS中的sendBroadcast方法。

3 ActivityManagerService

3.1 broadcastIntent

 public final int broadcastIntent(IApplicationThread caller,
            Intent intent, String resolvedType, IIntentReceiver resultTo,
            int resultCode, String resultData, Bundle resultExtras,
            String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean serialized, boolean sticky, int userId) {
        enforceNotIsolatedCaller("broadcastIntent");
        synchronized(this) {
            intent = verifyBroadcastLocked(intent);

            final ProcessRecord callerApp = getRecordForAppLocked(caller);
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            int res = broadcastIntentLocked(callerApp,
                    callerApp != null ? callerApp.info.packageName : null,
                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                    requiredPermissions, appOp, bOptions, serialized, sticky,
                    callingPid, callingUid, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

在broadcastIntent方法中调用了broadcastIntentLocked

3.2 broadcastIntentLocked

broadcastIntentLocked方法比较长,下面截取部分代码。
1 默认不发送给已经停止的应用

 // By default broadcasts do not go to stopped apps.
 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);

FLAG_EXCLUDE_STOPPED_PACKAGES标记为表示广播不会发送给已经停止的应用。

与此对应的是FLAG_INCLUDE_STOPPED_PACKAGES,表示广播会发送给已经停止的应用。

    public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 0x00000020;

2 根据intent-filte查找匹配的广播接收者。

if ((receivers != null && receivers.size() > 0)
                || resultTo != null) {
            BroadcastQueue queue = broadcastQueueForIntent(intent);
            //1 最终将满足条件的广播接受者添加到BroadcastRecord中
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, receivers, resultTo, resultCode,
                    resultData, resultExtras, ordered, sticky, false, userId);

            if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing ordered broadcast " + r
                    + ": prev had " + queue.mOrderedBroadcasts.size());
            if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST,
                    "Enqueueing broadcast " + r.intent.getAction());

            final BroadcastRecord oldRecord =
                    replacePending ? queue.replaceOrderedBroadcastLocked(r) : null;
            if (oldRecord != null) {
                // Replaced, fire the result-to receiver.
                if (oldRecord.resultTo != null) {
                    final BroadcastQueue oldQueue = broadcastQueueForIntent(oldRecord.intent);
                    try {
                        oldQueue.performReceiveLocked(oldRecord.callerApp, oldRecord.resultTo,
                                oldRecord.intent,
                                Activity.RESULT_CANCELED, null, null,
                                false, false, oldRecord.userId);
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Failure ["
                                + queue.mQueueName + "] sending broadcast result of "
                                + intent, e);

                    }
                }
            } else {
                queue.enqueueOrderedBroadcastLocked(r);
                //2 发送广播给响相应的广播接收器
                queue.scheduleBroadcastsLocked();
            }
        }

4 BroadcastQueue

4.1 scheduleBroadcastsLocked()

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

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

在此方法中,并没有去直接发送消息。而是使用handler发送了一个BROADCAST_INTENT_MSG消息。在其handler对应的handleMessage方法中,调用了processNextBroadcast方法

4.2 processNextBroadcast

此方法比较长,下面截取部分代码

 // First, deliver any non-serialized broadcasts right away.
			//1 遍历无序广播(普通广播)
            while (mParallelBroadcasts.size() > 0) {
                r = mParallelBroadcasts.remove(0);
                r.dispatchTime = SystemClock.uptimeMillis();
                r.dispatchClockTime = System.currentTimeMillis();

                if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                    Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
                        System.identityHashCode(r));
                    Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                        createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_DELIVERED),
                        System.identityHashCode(r));
                }

                final int N = r.receivers.size();
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast ["
                        + mQueueName + "] " + r);
                for (int i=0; i<N; i++) {
                    Object target = r.receivers.get(i);
                    if (DEBUG_BROADCAST)  Slog.v(TAG_BROADCAST,
                            "Delivering non-ordered on [" + mQueueName + "] to registered "
                            + target + ": " + r);
                    //2 将广播发给特定的广播接受者
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
                }
                addBroadcastToHistoryLocked(r);
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
                        + mQueueName + "] " + r);
            }

可以看出,最终通过deliverToRegisteredReceiverLocked方法发送广播。
deliverToRegisteredReceiverLocked
在此方法中又通过performReceiveLocked方法来发送广播

performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                        new Intent(r.intent), r.resultCode, r.resultData,
                        r.resultExtras, r.ordered, r.initialSticky, r.userId);

4.3 performReceiveLocked

performReceiveLocked方法如下所示,根据之前分析的service和activity的工作过程可知,此处的app.thread即为ApplicationThread。所以接着看ApplicationThread中的scheduleRegisteredReceiver方法。

 void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,
            Intent intent, int resultCode, String data, Bundle extras,
            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
        // Send the intent to the receiver asynchronously using one-way binder calls.
        if (app != null) {
            if (app.thread != null) {
                // If we have an app thread, do the call through that so it is
                // correctly ordered with other one-way calls.
                try {
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);
                // TODO: Uncomment this when (b/28322359) is fixed and we aren't getting
                // DeadObjectException when the process isn't actually dead.
                //} catch (DeadObjectException ex) {
                // Failed to call into the process.  It's dying so just let it die and move on.
                //    throw ex;
                } catch (RemoteException ex) {
                    // Failed to call into the process. It's either dying or wedged. Kill it gently.
                    synchronized (mService) {
                        Slog.w(TAG, "Can't deliver broadcast to " + app.processName
                                + " (pid " + app.pid + "). Crashing it.");
                        app.scheduleCrash("can't deliver broadcast");
                    }
                    throw ex;
                }
            } else {
                // Application has died. Receiver doesn't exist.
                throw new RemoteException("app.thread must not be null");
            }
        } else {
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
        }
    }

5 ApplicationThread

5.1 scheduleRegisteredReceiver

此方法内容较少,主要是通过InnerReceiver的performReceive方法来实现广播的接收。

 public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
                int resultCode, String dataStr, Bundle extras, boolean ordered,
                boolean sticky, int sendingUser, int processState) throws RemoteException {
            updateProcessState(processState, false);
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
        }

6 InnerReceiver

LoadedApk.ReceiverDispatcher.InnerReceiver

@Override
            public void performReceive(Intent intent, int resultCode, String data,
                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                final LoadedApk.ReceiverDispatcher rd;
                if (intent == null) {
                    Log.wtf(TAG, "Null intent received");
                    rd = null;
                } else {
                    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 = ActivityManager.getService();
                    try {
                        if (extras != null) {
                            extras.setAllowFds(false);
                        }
                        mgr.finishReceiver(this, resultCode, data, extras, false, intent.getFlags());
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
            }

通过方法中的这一段

if (rd != null) {
                    rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
                }

可知,调用了ReceiverDispatcherh中的performReceive方法。

7 LoadedApk.ReceiverDispatcher

7.1 performReceive

public void performReceive(Intent intent, int resultCode, String data,
                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
            //1 创建Args对象    
            final Args args = new Args(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
            if (intent == null) {
                Log.wtf(TAG, "Null intent received");
            } else {
                if (ActivityThread.DEBUG_BROADCAST) {
                    int seq = intent.getIntExtra("seq", -1);
                    Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
                            + " seq=" + seq + " to " + mReceiver);
                }
            }
            //2 通过mActivityThread.post()来执行args中的逻辑
            if (intent == null || !mActivityThread.post(args.getRunnable())) {
                if (mRegistered && ordered) {
                    IActivityManager mgr = ActivityManager.getService();
                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                            "Finishing sync broadcast to " + mReceiver);
                    args.sendFinished(mgr);
                }
            }
        }

在此方法中的这一行可知,Args中的run方法将会运行在主线程。

!mActivityThread.post(args.getRunnable())

8 LoadedApk.ReceiverDispatcher.Args

8.1 getRunnable

final BroadcastReceiver receiver = mReceiver;

receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);

可以看到,BroadCastReceiver的onReceive方法被执行了,也就是说应用已经接收到广播了。并且onReceive是在主线程中调用的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值