美文网首页
Android10.0 BroadcastReceiver工作原

Android10.0 BroadcastReceiver工作原

作者: 门心叼龙 | 来源:发表于2019-11-20 17:48 被阅读0次

    本文出自门心叼龙的博客,属于原创类容,转载请注明出处。

    BroadcastReceiver在Android四大组件中排行老三,它是一个广播接收器,用于系统中不同组件之间的通信,类似于事件编程中的事件监听器,只不过事件编程中监听的对象是控件,而广播接收器监听的对象是系统中的组件。广播分为普通广播,有序广播和粘性广播,本文主要研究普通广播的工作过程,包括广播接收器的注册、广播的发送、广播的接受背后的工作原理,其他两种类型都是类似的,大家可以触类旁通。

    BroadcastReceiver的基本用法

    首先需要定义一个广播接收器,如下所示:

    public class MyReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.v("MYTAG","onReceive start...");
        }
    }
    

    定义一个广播接收器的过程很简单,直接继承BroadcastReceiver这个抽象类,并实现它的抽象方法onReceive即可。广播接收器定义完毕,接下来的工作是注册广播,广播的注册分为动态注册和静态注册,大家注意了BroadcastReveiver是四大组件中唯一可以动态注册的组件,静态注册比较简单直接可以在清单文件AndroidMinifest.xml中通过receiver标签完成,我们主要看动态注册:

    registerReceiver(new MyReceiver(),new IntentFilter("com.test.receiver"));
    

    直接调用Context给我们提供的registerReceiver即可完成广播接收器的注册,该方法需要传入两个参数,第一个参数就是我们前面所定义的广播接收器MyReceiver对象,第二个参数是一个IntentFilter,它主要用来过滤广播的。广播接收器注册完成,最后一步就是发送广播了,代码实现如下:

    sendBroadcast(new Intent("com.test.receiver"));
    

    发送之后广播接收器MyReceiver就可以收到消息了,onReceive的方法响应了,打印日志如下:

    2019-11-18 09:22:35.522 2721-2721/com.mxdl.customview V/MYTAG: onReceive start...
    

    这样我们就轻轻轻松的体验了一把BroadcastReceiver的基本用法,接下来我们来看广播接收器的注册,广播发送,以及广播的接收他们背后的工作原理。

    BroadcastReceiver的注册过程

    ContextImpl中的流程

    注册过程是从ContextWraper的registerReceiver方法开始的,如下所示:

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

    ContextWraper的registerReceiver方法很简单只有一行,ContextWraper什么都没有做,就把注册的工作交给了mBase,mBase在前面几篇文章我们多次提到过,在这里就不在重复讲解了,它就是ContextImpl,接下来,我们看ContextImpl的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(), 0);
        }
    

    registerReceiver方法回重载调用一次,然后再调用自己的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();
                    }
                    rd = mPackageInfo.getReceiverDispatcher(
                        receiver, context, scheduler,
                        mMainThread.getInstrumentation(), true);
                } else {
                    if (scheduler == null) {
                        scheduler = mMainThread.getHandler();
                    }
                    //注释1
                    rd = new LoadedApk.ReceiverDispatcher(
                            receiver, context, scheduler, null, true).getIIntentReceiver();
                }
            }
            try {
                //注释2
                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();
            }
        }
    

    我们主要看注释1处,将传递过来的receiver转化为了IIntentReceiver,我们看ReceiverDispatcher的getIIntentReceiver方法返回的到底是什么,如下所示:

    final IIntentReceiver.Stub mIIntentReceiver;
     @UnsupportedAppUsage
            IIntentReceiver getIIntentReceiver() {
                return mIIntentReceiver;
            }
    

    一目了然,返回的是一个IIntentReceiver.Stub类型的变量mIIntentReceiver,我看mIIntentReceiver是在什么时候初始化的,经过变量跟踪我们可以知道,就是在ReceiverDispatcher对象实例化的时候就赋值了,代码实现如下:

    ReceiverDispatcher(BroadcastReceiver receiver, Context context,
                    Handler activityThread, Instrumentation instrumentation,
                    boolean registered) {
                if (activityThread == null) {
                    throw new NullPointerException("Handler must not be null");
                }
                //注释1
                mIIntentReceiver = new InnerReceiver(this, !registered);
                mReceiver = receiver;
                mContext = context;
                mActivityThread = activityThread;
                mInstrumentation = instrumentation;
                mRegistered = registered;
                mLocation = new IntentReceiverLeaked(null);
                mLocation.fillInStackTrace();
            }
    

    在注释1处mIIntentReceiver变量被初始化了,它的具体实现就是InnerReceiver,它的继承关系如下:

    final static class InnerReceiver extends IIntentReceiver.Stub
    

    到了这一步我们也就明白了,客户端会将BroadcastReceiver对象转换为一个ReceiverDispatcher.InnerReceiver对象,之所以不能直接传递BroadcastReceiver对象是因为广播的发送有可能是跨进程的,BroadcastReceiver只能借助于Binder对象才能在服务端回调自己的方法,而ReceiverDispatcher的内部类InnerReceiver正好充当了Binder这个角色。ReceiverDispatcher同时持有BroadcastReceiver和InnerReceiver,
    InnerReceiver反向持有ReceiverDispatcher。我们有没有发现,这和上一篇我们在学习Service绑定的时候是一个套路,ServiceConnetion对象也是被转化为ServiceDispatcher.InnerConnection对象传递的。

    回过头我们再看ContextImple对象的registerReceiverInternal方法的注释2处调用了ActivityManager.getService()对象的registerReceiver方法此时把InnerReceiver对象传递给给服务端了,ActivityManager.getService()对象不用多想就是ActivityManagerService对象,现在我们看registerReceiver方法的实现,如下所示:

    ActivityManagerService中的流程
    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
                IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
                int flags) {
        ...
        if (rl == null) {
                    rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                            userId, receiver);
                    if (rl.app != null) {
                        final int totalReceiversForApp = rl.app.receivers.size();
                        if (totalReceiversForApp >= MAX_RECEIVERS_ALLOWED_PER_APP) {
                            throw new IllegalStateException("Too many receivers, total of "
                                    + totalReceiversForApp + ", registered for pid: "
                                    + rl.pid + ", callerPackage: " + callerPackage);
                        }
                        rl.app.receivers.add(rl);
                    } else {
                        try {
                            receiver.asBinder().linkToDeath(rl, 0);
                        } catch (RemoteException e) {
                            return sticky;
                        }
                        rl.linkedToDeath = true;
                    }
                    //注释1
                    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
                            + " callerPackage is " + callerPackage);
                } else if (rl.pid != callingPid) {
                    throw new IllegalArgumentException(
                            "Receiver requested to register for pid " + callingPid
                            + " was previously registered for pid " + rl.pid
                            + " callerPackage is " + callerPackage);
                } else if (rl.userId != userId) {
                    throw new IllegalArgumentException(
                            "Receiver requested to register for user " + userId
                            + " was previously registered for user " + rl.userId
                            + " callerPackage is " + callerPackage);
                }
                BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                        permission, callingUid, userId, instantApp, visibleToInstantApps);
                if (rl.containsFilter(filter)) {
                    Slog.w(TAG, "Receiver with filter " + filter
                            + " already registered for pid " + rl.pid
                            + ", callerPackage is " + callerPackage);
                } else {
                    rl.add(bf);
                    if (!bf.debugCheck()) {
                        Slog.w(TAG, "==> For Dynamic broadcast");
                    }
                    //注释2
                    mReceiverResolver.addFilter(bf);
                }
                ...
    

    服务端的registerReceiver是实现广播注册的真正方法,该方法很长我们只看重要的部分,在注释1处将客户端传递过来的广播接收器InnerReceiver保存起来,在最后的注释2处将客户端传递过来的IntentFilter也保存起来,这样整个广播注册过程就完成了。

    广播的发送和接收

    ContextImpl中的流程

    接下来我们看广播的发送和接收过程,和广播注册一样,广播发送也是从ContextWraper的sendBroadcast方法开始的,方法如下:

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

    该方法里面什么也没有做,直接就把发送的工作交给了ContextImple的sendBroadcast方法了,该方法实现如下:

     @Override
        public void sendBroadcast(Intent intent) {
            warnIfCallingFromSystemProcess();
            String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
            try {
                intent.prepareToLeaveProcess(this);
                //注释1
                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();
            }
        }
    
    ActivityManagerService中的流程

    在注释1处调用了ActivityManagerService的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();
                try {
                    //注释1
                    return broadcastIntentLocked(callerApp,
                            callerApp != null ? callerApp.info.packageName : null,
                            intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                            requiredPermissions, appOp, bOptions, serialized, sticky,
                            callingPid, callingUid, callingUid, callingPid, userId);
                } finally {
                    Binder.restoreCallingIdentity(origId);
                }
            }
        }
    

    ActivityManagerService的broadcastIntent方法也不长,在方法的最后会调用它的broadcastIntentLocked方法,该方法会被重载调用一次,broadcastIntentLocked方法的具体实现如下:

      @GuardedBy("this")
        final int broadcastIntentLocked(ProcessRecord callerApp,
                String callerPackage, Intent intent, String resolvedType,
                IIntentReceiver resultTo, int resultCode, String resultData,
                Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
                boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
                int realCallingPid, int userId, boolean allowBackgroundActivityStarts) {
     ...
     int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
            if (!ordered && NR > 0) {
                // If we are not serializing this broadcast, then send the
                // registered receivers separately so they don't wait for the
                // components to be launched.
                if (isCallerSystem) {
                    checkBroadcastFromSystem(intent, callerApp, callerPackage, callingUid,
                            isProtectedBroadcast, registeredReceivers);
                }
                //注释1
                final BroadcastQueue queue = broadcastQueueForIntent(intent);
                BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                        callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                        requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                        resultCode, resultData, resultExtras, ordered, sticky, false, userId,
                        allowBackgroundActivityStarts, timeoutExempt);
                if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Enqueueing parallel broadcast " + r);
                final boolean replaced = replacePending
                        && (queue.replaceParallelBroadcastLocked(r) != null);
                // Note: We assume resultTo is null for non-ordered broadcasts.
                if (!replaced) {
                    queue.enqueueParallelBroadcastLocked(r);
                    //注释2
                    queue.scheduleBroadcastsLocked();
                }
                registeredReceivers = null;
                NR = 0;
            }
            ...
    

    这个方法的很长,但是他只做了一件事,通过传递过来的Intent查找相匹配的的BroadcastReceiver并把它放入到广播队列BroadcastQueue中,如注释1所示,接下来会调用注释2处的scheduleBroadcastsLocked方法执行广播发送任务,下面是BroadcastQueue的scheduleBroadcastsLocked方法的具体实现:

    BroadcastQueue中的流程
    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;
        }
    

    该方法的逻辑实现也不是很长,就向消息管理器mHandler发送了一个BROADCAST_INTENT_MSG类型的消息,mHandler收到消息后回调它自己的processNextBroadcast方法,processNextBroadcast方法又会调用processNextBroadcastLocked方法,它的具体实现如下:

      final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
            BroadcastRecord r;
            ...
            // First, deliver any non-serialized broadcasts right away.
            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);
                    //注释1     
                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
                }
                addBroadcastToHistoryLocked(r);
                if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast ["
                        + mQueueName + "] " + r);
            }
            ...
    

    这个方法的实现还是很长的,我么主要看注释1处,它调用了deliverToRegisteredReceiverLocked

    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
                BroadcastFilter filter, boolean ordered, int index) {
        try {
                if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST,
                        "Delivering to " + filter + " : " + r);
                if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {
                    // Skip delivery if full backup in progress
                    // If it's an ordered broadcast, we need to continue to the next receiver.
                    if (ordered) {
                        skipReceiverLocked(r);
                    }
                } else {
                    r.receiverTime = SystemClock.uptimeMillis();
                    maybeAddAllowBackgroundActivityStartsToken(filter.receiverList.app, r);
                    //注释1
                    performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,
                            new Intent(r.intent), r.resultCode, r.resultData,
                            r.resultExtras, r.ordered, r.initialSticky, r.userId);
                    // parallel broadcasts are fire-and-forget, not bookended by a call to
                    // finishReceiverLocked(), so we manage their activity-start token here
                    if (r.allowBackgroundActivityStarts && !r.ordered) {
                        postActivityStartTokenRemoval(filter.receiverList.app, r);
                    }
                }
                if (ordered) {
                    r.state = BroadcastRecord.CALL_DONE_RECEIVE;
                }
            }
        }
    

    紧接着会调用注释1处的performReceiveLocked方法,该方法实现如下:

    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 {
                        //注释1
                        app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                                data, extras, ordered, sticky, sendingUser, app.getReportedProcState());
                    // 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);
            }
        }
    

    最终会执行app.thread对象的scheduleRegisteredReceiver方法,app.thread对象是ActivityThread的内部类对象ApplicationThread,这个在前面几篇文章多次提到过,在这里也就不做过多的解释,我们继续跟进ApplicationThread对象的scheduleRegisteredReceiver方法,它的实现如下:

    ApplicationThread中的流程
     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);
            }
    

    在客户端更新进程状态之后经过短暂的停留,随着receiver对象的performReceive的调用流程再次回到服务端进程,receiver是不是熟悉?就是在前面我们在讲ContextImpl对象的registerReceiverInternal方法的时候所提到的ReceiverDispatcher.InnerReceiver对象,下面我们来看看InnerReceiver对象的performReceive方法的实现,如下所示:

    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) {
                        //注释1
                        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();
                        }
                    }
                }
    

    在performReceive方法的注释1处会调用ReceiverDispatcher对象的performReceive方法,该方法如下所示:

    public void performReceive(Intent intent, int resultCode, String data,
                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                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);
                    }
                }
                //注释1
                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);
                    }
                }
            }
    

    在注释1处给ActivityThread的消息管理器发送一个args.getRunnable类型回调的消息,下面就是该回调的具体实现:

    public final Runnable getRunnable() {
                    return () -> {
                        final BroadcastReceiver receiver = mReceiver;
                        final boolean ordered = mOrdered;
    
                        if (ActivityThread.DEBUG_BROADCAST) {
                            int seq = mCurIntent.getIntExtra("seq", -1);
                            Slog.i(ActivityThread.TAG, "Dispatching broadcast " + mCurIntent.getAction()
                                    + " seq=" + seq + " to " + mReceiver);
                            Slog.i(ActivityThread.TAG, "  mRegistered=" + mRegistered
                                    + " mOrderedHint=" + ordered);
                        }
    
                        final IActivityManager mgr = ActivityManager.getService();
                        final Intent intent = mCurIntent;
                        if (intent == null) {
                            Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched
                                    + (mRunCalled ? ", run() has already been called" : ""));
                        }
    
                        mCurIntent = null;
                        mDispatched = true;
                        mRunCalled = true;
                        if (receiver == null || intent == null || mForgotten) {
                            if (mRegistered && ordered) {
                                if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                                        "Finishing null broadcast to " + mReceiver);
                                sendFinished(mgr);
                            }
                            return;
                        }
    
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveReg");
                        try {
                            ClassLoader cl = mReceiver.getClass().getClassLoader();
                            intent.setExtrasClassLoader(cl);
                            intent.prepareToEnterProcess();
                            setExtrasClassLoader(cl);
                            receiver.setPendingResult(this);
                            //注释1
                            receiver.onReceive(mContext, intent);
                        } catch (Exception e) {
                            if (mRegistered && ordered) {
                                if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
                                        "Finishing failed broadcast to " + mReceiver);
                                sendFinished(mgr);
                            }
                            if (mInstrumentation == null ||
                                    !mInstrumentation.onException(mReceiver, e)) {
                                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                                throw new RuntimeException(
                                        "Error receiving broadcast " + intent
                                                + " in " + mReceiver, e);
                            }
                        }
    
                        if (receiver.getPendingResult() != null) {
                            finish();
                        }
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    };
                }
    

    在注释1处广播接收器BroadcastReceiver的onReceive方法被回调了,至此整个广播接收器的注册、广播的发送、广播的接收所有的流程就全部走完了,最后我画了两幅流程图,方便大家对整个流程的理解。

    总结

    注册流程
    在这里插入图片描述

    ContextWraper.registerReceiver
    ContextImpl.registerReceiver
    ContextImpl.registerReceiverInternal
    ActivityManagerService.registerReceiver

    发送接收流程
    在这里插入图片描述

    ContextWraper.sendBroadcast
    ContextImpl.sendBroadcast
    ActivityManagerService.broadcastIntent
    ActivityManagerService.broadcastIntentLocked
    BroadcastQueue.scheduleBroadcastsLocked
    BroadcastQueue.processNextBroadcastLocked
    BroadcastQueue.deliverToRegisteredReceiverLocked
    BroadcastQueue.performReceiveLocked
    ApplicationThread.scheduleRegisteredReceiver
    InnerReceiver.performReceive
    ReceiverDispatcher.performReceive
    BroadcastReceiver.onReceive

    问题反馈

    在使用学习中有任何问题,请留言,或加入Android、Java开发技术交流群

    相关文章

      网友评论

          本文标题:Android10.0 BroadcastReceiver工作原

          本文链接:https://www.haomeiwen.com/subject/vcfaictx.html