4 广播的处理

广播的处理都会调用BroadcastQueue下的scheduleBroadcastsLocked(),接下我们来看看这个函数

4.1 scheduleBroadcastsLocked

文件:BroadcastQueue.java

    public void scheduleBroadcastsLocked() {        if (mBroadcastsScheduled) {            return;        }        // 见4.1.1        mHandler.sendMessage(mHandler.obtainMessage(BROADCAST_INTENT_MSG, this));        mBroadcastsScheduled = true;    }

mBroadcastsScheduled这个boolean的意思是如果当前真好有一个BROADCAST_INTENT_MSG在执行,那么mBroadcastsScheduled为true,否则为false

4.1.1 BroadcastHandler

文件:BroadcastQueue.java

private final class BroadcastHandler extends Handler {        ......        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case BROADCAST_INTENT_MSG: {                    // 见4.2                    processNextBroadcast(true);                } break;                ......            }        }    }

最重要的就是processNextBroadcast,广播处理会多次调用它

4.2 processNextBroadcast

文件:BroadcastQueue.java
这个函数有500多行,我们分开来讲

4.2.1 非串行广播的处理

            // 如果是从BroadcastHandler中调用来的,则fromMsg为true,mBroadcastsScheduled为false            if (fromMsg) {                mBroadcastsScheduled = false;            }            // 首先,立即发送所有的非串行广播            while (mParallelBroadcasts.size() > 0) {                r = mParallelBroadcasts.remove(0); // 每次都从一个开始                r.dispatchTime = SystemClock.uptimeMillis();  // 分发时间                r.dispatchClockTime = System.currentTimeMillis();  // 分发时间                final int N = r.receivers.size();                for (int i=0; iget(i);                    // 将广播发给BroadcastRecord所有的Receiver,见4.3                    deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);                }                addBroadcastToHistoryLocked(r); //将广播添加历史统计            }

这部分主要是对非串行广播进行发送,通过两层循环来发送所有的Receiver,接下来看看串行发送的广播

4.2.2 串行广播的处理

            if (mPendingBroadcast != null) {                boolean isDead;                synchronized (mService.mPidsSelfLocked) {                    // 拿到正在处理广播的进程,并判断它是否死亡                    ProcessRecord proc = mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid);                    isDead = proc == null || proc.crashing;                }                if (!isDead) {                    // 如果处理广播的进程保持活跃状态,则继续等待                    return;                } else {                    mPendingBroadcast.state = BroadcastRecord.IDLE;                    mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;                    mPendingBroadcast = null;                }            }

判断处理广播的进程是否保持活跃状态,如果是,则继续等待其完成

            boolean looped = false;            do {                if (mOrderedBroadcasts.size() == 0) {                    // 所有串行广播执行完毕,则执行GC操作                    mService.scheduleAppGcsLocked();                    if (looped) {                        mService.updateOomAdjLocked();                    }                    return;                }                // 拿串行广播中的第一个                r = mOrderedBroadcasts.get(0);                boolean forceReceive = false;                // 该ReceiverList中所有接收者的数量                int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;                // AMS已经注册启动完成,并且不是该r第一次进这个循环了                if (mService.mProcessesReady && r.dispatchTime > 0) {                    long now = SystemClock.uptimeMillis()                    // 出现超时                    if ((numReceivers > 0) &&                            (now > r.dispatchTime + (2*mTimeoutPeriod*numReceivers))) {                        broadcastTimeoutLocked(false); // 强制结束这个广播                        forceReceive = true;                        r.state = BroadcastRecord.IDLE;                    }                }                if (r.state != BroadcastRecord.IDLE) {                    return;                }

每次都会取mOrderedBroadcasts中的第一个元素,然后判断是否超时,如果超时,则强制结束这个广播,并且这个BroadcastRecord剩下的广播接收器也将收不到广播。超时的依据是:2*mTimeoutPeriod*numReceivers,其中mTimeoutPeriod为(前台广播为10s,后台广播为60s),numReceivers为接收器的数量;接着如果BroadcastRecord的state不等于BroadcastRecord.IDLE,就返回

                // 要么是广播已经向所有的receiver发送完毕,要么是被强制停止                if (r.receivers == null || r.nextReceiver >= numReceivers                        || r.resultAbort || forceReceive) {                    if (r.resultTo != null) {                        try {                            // 处理广播消息,调用onReceive(),见4.3.1                            performReceiveLocked(r.callerApp, r.resultTo,                                new Intent(r.intent), r.resultCode,                                r.resultData, r.resultExtras, false, false, r.userId);                            r.resultTo = null;                        } catch (RemoteException e) {                            r.resultTo = null;                        }                    }                    // 取消BROADCAST_TIMEOUT_MSG消息,见4.2.3                    cancelBroadcastTimeoutLocked();                    addBroadcastToHistoryLocked(r);                    if (r.intent.getComponent() == null && r.intent.getPackage() == null                            && (r.intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {                        mService.addBroadcastStatLocked(r.intent.getAction(), r.callerPackage,                                r.manifestCount, r.manifestSkipCount, r.finishTime-r.dispatchTime);                    }                    mOrderedBroadcasts.remove(0);                    r = null;                    looped = true;                    continue;                }            } while (r == null);

当Broadcasts中所有的receiver都收到了广播或者被强制结束了广播,都会调用performReceiveLocked;另外如果是取到BroadcastRecord第一次进来这个循环,将之前出来,因为不满足while (r == null)

            // 获取下一个需要处理的Receiver的序号            int recIdx = r.nextReceiver++;            // 这个BroadcastRecord开始处理这个Receiver的时间            r.receiverTime = SystemClock.uptimeMillis();            // 如果是BroadcastRecord中第一个Receiver            if (recIdx == 0) {                r.dispatchTime = r.receiverTime;                r.dispatchClockTime = System.currentTimeMillis();            }            if (! mPendingBroadcastTimeoutMessage) {                long timeoutTime = r.receiverTime + mTimeoutPeriod;                // 见4.2.4                setBroadcastTimeoutLocked(timeoutTime);            }
  • 获取下一个要处理的Receiver

  • 获取当前处理这个Receiver的时间,用于处理ANR问题,如果是当前处理的是第一个Receiver,你们dispatchTime时间和receiverTime相等,用于处理整个BroadcastRecord的超时问题

  • mPendingBroadcastTimeoutMessage的初始值是false,然后设置针对该Receiver的超时处理,超时就会造成ANR;超时的时间为10s(前台广播)或者60s(后台广播)

            final BroadcastOptions brOptions = r.options;            final Object nextReceiver = r.receivers.get(recIdx);            // 如果是动态注册的有序广播            if (nextReceiver instanceof BroadcastFilter) {                BroadcastFilter filter = (BroadcastFilter)nextReceiver;                // 发送该动态注册的有序广播,见4.3                deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);                if (r.receiver == null || !r.ordered) {                    r.state = BroadcastRecord.IDLE;                    scheduleBroadcastsLocked();                } else {                    if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {                        scheduleTempWhitelistLocked(filter.owningUid,                                brOptions.getTemporaryAppWhitelistDuration(), r);                    }                }                return;            }

判断当前这个接收器是不是动态注册的,如果是动态注册的,就用deliverToRegisteredReceiverLocked发送,最后return,结束processNextBroadcast这个函数

            ResolveInfo info =                (ResolveInfo)nextReceiver;            ComponentName component = new ComponentName(                    info.activityInfo.applicationInfo.packageName,                    info.activityInfo.name);            ......// 主要进行一些权限检查,如果不满足条件skip置为true,跳过这个receiver            if (skip) {                r.delivery[recIdx] = BroadcastRecord.DELIVERY_SKIPPED;                r.receiver = null;                r.curFilter = null;                r.state = BroadcastRecord.IDLE;                scheduleBroadcastsLocked();                return;            }            r.delivery[recIdx] = BroadcastRecord.DELIVERY_DELIVERED;            r.state = BroadcastRecord.APP_RECEIVE;            r.curComponent = component;            r.curReceiver = info.activityInfo;            if (brOptions != null && brOptions.getTemporaryAppWhitelistDuration() > 0) {                scheduleTempWhitelistLocked(receiverUid,                        brOptions.getTemporaryAppWhitelistDuration(), r);            }            // 广播已经开始执行了,这个包不能被停止            try {                AppGlobals.getPackageManager().setPackageStoppedState(                        r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));            } catch (RemoteException e) {            } catch (IllegalArgumentException e) {                Slog.w(TAG, "Failed trying to unstop package "                        + r.curComponent.getPackageName() + ": " + e);            }            // 检查目标进程是否已经运行            if (app != null && app.thread != null) {                try {                    app.addPackage(info.activityInfo.packageName,                            info.activityInfo.applicationInfo.versionCode, mService.mProcessStats);                    //将广播发送给目标进程,见4.2.5                    processCurBroadcastLocked(r, app);                    return;                } catch (RemoteException e) {                    Slog.w(TAG, "Exception when sending broadcast to "                          + r.curComponent, e);                } catch (RuntimeException e) {                    logBroadcastReceiverDiscardLocked(r);                    finishReceiverLocked(r, r.resultCode, r.resultData,                            r.resultExtras, r.resultAbort, false);                    scheduleBroadcastsLocked();                    // 如果启动receiver失败,需要重置state                    r.state = BroadcastRecord.IDLE;                    return;                }            }            // 如果目标进程没有启动,则需要将他启动,见4.2.6            if ((r.curApp=mService.startProcessLocked(targetProcess,                    info.activityInfo.applicationInfo, true,                    r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,                    "broadcast", r.curComponent,                    (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false))                            == null) {                // 这个接收器不能使用                logBroadcastReceiverDiscardLocked(r);                finishReceiverLocked(r, r.resultCode, r.resultData,                        r.resultExtras, r.resultAbort, false);                scheduleBroadcastsLocked();                r.state = BroadcastRecord.IDLE;                return;            }            mPendingBroadcast = r;            mPendingBroadcastRecvIndex = recIdx;

处理静态注册下广播的发送,如果进程已经启动,则用processCurBroadcastLocked发送,然后返回,AMS等待广播接收的结果,以便进行下一个receiver发送广播,如果超时,就会触发ANR;
如果没有启动,则AMS调用startProcessLocked来启动接收者进程,启动的时候,将当前这个BroadcastRecord放到mPendingBroadcast中保存,把receiver的序号放到mPendingBroadcastRecvIndex中保存,应用启动完毕后会通知AMS,然后在进行广播发送

4.2.3 cancelBroadcastTimeoutLocked 取消超时

文件:BroadcastQueue.java

    final void cancelBroadcastTimeoutLocked() {        if (mPendingBroadcastTimeoutMessage) {            mHandler.removeMessages(BROADCAST_TIMEOUT_MSG, this);            mPendingBroadcastTimeoutMessage = false;        }    }

意思就是移除BROADCAST_TIMEOUT_MSG这个消息,不进行超时的处理了

4.2.4 setBroadcastTimeoutLocked 设置超时

    final void setBroadcastTimeoutLocked(long timeoutTime) {        if (! mPendingBroadcastTimeoutMessage) {            Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG, this);            mHandler.sendMessageAtTime(msg, timeoutTime);            mPendingBroadcastTimeoutMessage = true;        }    }

由mHandler.sendMessageAtTime(msg, timeoutTime)可以看出,如果超时了就会发送消息BROADCAST_TIMEOUT_MSG

4.2.5 processCurBroadcastLocked

文件:BroadcastQueue.java

    private final void processCurBroadcastLocked(BroadcastRecord r,            ProcessRecord app) throws RemoteException {        if (app.thread == null) {            throw new RemoteException();        }        if (app.inFullBackup) {            skipReceiverLocked(r);            return;        }        r.receiver = app.thread.asBinder();        r.curApp = app;        app.curReceiver = r;        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);        mService.updateLruProcessLocked(app, false, null);        mService.updateOomAdjLocked();        // 告诉应用启动receiver.        r.intent.setComponent(r.curComponent);        boolean started = false;        try {            mService.notifyPackageUse(r.intent.getComponent().getPackageName(),                                      PackageManager.NOTIFY_PACKAGE_USE_BROADCAST_RECEIVER);            // 见4.4处理静态广播            app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,                    mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),                    r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId,                    app.repProcState);            started = true;        } finally {            if (!started) {                r.receiver = null;                r.curApp = null;                app.curReceiver = null;            }        }    }

这里最重要的是scheduleReceiver

4.2.6 启动进程后通知AMS

流程如下:

  • ActivityThread.Main

  • ActivityThread.attach

  • AMS. attachApplication

  • AMS. attachApplicationLocked

到了attachApplicationLocked之后里面一行这样的代码:

didSomething |= sendPendingBroadcastsLocked(app);

我们继续看看sendPendingBroadcastsLocked

    boolean sendPendingBroadcastsLocked(ProcessRecord app) {        boolean didSomething = false;        for (BroadcastQueue queue : mBroadcastQueues) {            didSomething |= queue.sendPendingBroadcastsLocked(app);        }        return didSomething;    }

主要是这行didSomething |= queue.sendPendingBroadcastsLocked(app),我们继续追

    public boolean sendPendingBroadcastsLocked(ProcessRecord app) {        boolean didSomething = false;        final BroadcastRecord br = mPendingBroadcast;        if (br != null && br.curApp.pid == app.pid) {            if (br.curApp != app) {                return false;            }            try {                mPendingBroadcast = null;                // 发送广播,见4.2.5                processCurBroadcastLocked(br, app);                didSomething = true;            } catch (Exception e) {                logBroadcastReceiverDiscardLocked(br);                finishReceiverLocked(br, br.resultCode, br.resultData,                        br.resultExtras, br.resultAbort, false);                scheduleBroadcastsLocked();                // We need to reset the state if we failed to start the receiver.                br.state = BroadcastRecord.IDLE;                throw new RuntimeException(e.getMessage());            }        }        return didSomething;    }

从mPendingBroadcast取出正在等待的BroadcastRecord,然后将mPendingBroadcast置为null,接着用processCurBroadcastLocked发送广播

4.3 deliverToRegisteredReceiverLocked 用来发送所有动态注册的广播

文件:BroadcastQueue.java

    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,            BroadcastFilter filter, boolean ordered, int index) {        boolean skip = false;        if (filter.requiredPermission != null) {            int perm = mService.checkComponentPermission(filter.requiredPermission,                    r.callingPid, r.callingUid, -1, true);            // 如果接收者没有权限,skip为true            if (perm != PackageManager.PERMISSION_GRANTED) {                skip = true;            }            ......        }        ...... //中间这很长一大串代码都是用来检查权限,如果不符合要求skip会置为true        if (skip) {            // 将状态改为DELIVERY_SKIPPED            r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;            return;        }        // 复查一下权限        if (Build.PERMISSIONS_REVIEW_REQUIRED) {            if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName,                    filter.owningUserId)) {                r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;                return;            }        }        r.delivery[index] = BroadcastRecord.DELIVERY_DELIVERED;        // 如果是有序的动态广播        if (ordered) {            r.receiver = filter.receiverList.receiver.asBinder();            r.curFilter = filter;            filter.receiverList.curBroadcast = r;            r.state = BroadcastRecord.CALL_IN_RECEIVE;            if (filter.receiverList.app != null) {                r.curApp = filter.receiverList.app;                filter.receiverList.app.curReceiver = r;                mService.updateOomAdjLocked(r.curApp);            }        }        try {            if (filter.receiverList.app != null && filter.receiverList.app.inFullBackup) {                if (ordered) {                    skipReceiverLocked(r);                }            } else {                // 发送动态注册的广播,见4.3.1                performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver,                        new Intent(r.intent), r.resultCode, r.resultData,                        r.resultExtras, r.ordered, r.initialSticky, r.userId);            }            if (ordered) {                r.state = BroadcastRecord.CALL_DONE_RECEIVE;            }        }         ......    }
  • 进来时首先检查权限,不满足的将skip设置为true,并将对应的receiver的状态设置为DELIVERY_DELIVERED

  • 如果是有序的动态广播,以一种同步的方式发送广播,并且在BroadcastRecord中保存receiver,curFilter和state,其中state为CALL_IN_RECEIVE

  • 通过performReceiveLocked发送动态注册的广播

  • 如果有序的动态广播,state改为CALL_DONE_RECEIVE

4.3.1 performReceiveLocked

文件:BroadcastQueue.java

    void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,            Intent intent, int resultCode, String data, Bundle extras,            boolean ordered, boolean sticky, int sendingUser) throws RemoteException {        // 进程已经启动的情况,用binder异步机制向receiver发送数据        if (app != null) {            if (app.thread != null) {                try {                    // 见4.3.2                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,                            data, extras, ordered, sticky, sendingUser, app.repProcState);                } catch (RemoteException ex) {                    synchronized (mService) {                        app.scheduleCrash("can't deliver broadcast");                    }                    throw ex;                }            } else {                // 应用已经死亡,Receiver不存在                throw new RemoteException("app.thread must not be null");            }        } else {            // 调用进程为null时,则走这个分支            receiver.performReceive(intent, resultCode, data, extras, ordered,                    sticky, sendingUser);        }    }

这里分为两种情况:

  • 调用进程和app.thread都不为null,这时通过binder方式向注册进程发起调用,其中Binder调用里会加上IBinder.FLAG_ONEWAY标记
    调用流程为:

  • 调用进程为null,这时执行receiver.performReceive(intent, resultCode, data, extras, ordered,sticky, sendingUser);

其中app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,data, extras, ordered, sticky, sendingUser, app.repProcState)的调用流程为:

  • ApplicationThreadNative.ApplicationThreadProxy. scheduleRegisteredReceiver(system_server进程)

  • Binder驱动(Binder驱动进程,ONEWAY)

  • ApplicationThreadNative. scheduleRegisteredReceiver(应用进程,Binder线程向主线程发送消息)

  • Binder驱动返回 (Binder驱动进程)

  • ActivityThread. scheduleRegisteredReceiver(应用进程,处理消息)

4.3.2 scheduleRegisteredReceiver

        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);            // 见4.3.3            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,                    sticky, sendingUser);        }

4.3.3 performReceive

这是LoadedApk.ReceiverDispatcher.InnerReceiver.performReceive

            public void performReceive(Intent intent, int resultCode, String data,                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {                final LoadedApk.ReceiverDispatcher rd;                ......                if (rd != null) {                    // 见4.3.4                    rd.performReceive(intent, resultCode, data, extras,                            ordered, sticky, sendingUser);                }                 ......            }

4.3.4 ReceiverDispatcher.performReceive

文件:LoadedApk.java

        public void performReceive(Intent intent, int resultCode, String data,                Bundle extras, boolean ordered, boolean sticky, int sendingUser) {            // 见4.3.5            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);                }            }            // 将广播信息放到args中,post到主线程中执行,见4.3.5            if (intent == null || !mActivityThread.post(args)) {                if (mRegistered && ordered) {                    IActivityManager mgr = ActivityManagerNative.getDefault();                    if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,                            "Finishing sync broadcast to " + mReceiver);                    // 告诉AMS,广播处理完毕,动态的有序广播会走这里见4.3.6                    args.sendFinished(mgr);                }            }        }

4.3.5 Args

final class Args extends BroadcastReceiver.PendingResult implements Runnable {            private Intent mCurIntent;            private final boolean mOrdered;            private boolean mDispatched;            public Args(Intent intent, int resultCode, String resultData, Bundle resultExtras,                    boolean ordered, boolean sticky, int sendingUser) {                super(resultCode, resultData, resultExtras,                        mRegistered ? TYPE_REGISTERED : TYPE_UNREGISTERED, ordered,                        sticky, mIIntentReceiver.asBinder(), sendingUser, intent.getFlags());                mCurIntent = intent;                mOrdered = ordered;            }            public void run() {                final BroadcastReceiver receiver = mReceiver;                final boolean ordered = mOrdered;                final IActivityManager mgr = ActivityManagerNative.getDefault();                final Intent intent = mCurIntent;                if (intent == null) {                    Log.wtf(TAG, "Null intent being dispatched, mDispatched=" + mDispatched);                }                mCurIntent = null;                mDispatched = true;                if (receiver == null || intent == null || mForgotten) {                    if (mRegistered && ordered) {                        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);                    // 调用接收者BroadcastReceiver.onReceive()                    receiver.onReceive(mContext, intent);                } catch (Exception e) {                    if (mRegistered && ordered) {                        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) {                    // 见4.3.6                    finish();                }                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);            }        }

这里主要调用的是receiver.onReceive(mContext, intent),至此非串行的动态注册的广播已经接收完毕,值得一提的是下面那个finish()函数,作用是结束这个广播,并将结果发送给下一个广播

4.3.6 sendFinished

文件:BroadcastReceiver.java

        public void sendFinished(IActivityManager am) {            synchronized (this) {                if (mFinished) {                    throw new IllegalStateException("Broadcast already finished");                }                mFinished = true;                try {                    if (mResultExtras != null) {                        mResultExtras.setAllowFds(false);                    }                    // 是否是有序的                    if (mOrderedHint) {                        // 见4.3.7                        am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,                                mAbortBroadcast, mFlags);                    } else {                        // 什么都不干,目的是告诉ActivityManager,这个广播我处理我完了                        am.finishReceiver(mToken, 0, null, null, false, mFlags);                    }                } catch (RemoteException ex) {                }            }        }

通过前面的分析,我们知道,动态广播如果是无序,在执行finish的时候,因为mType等于TYPE_REGISTERED,ordered为false,所以什么都不执行;只有有序的动态广播最终调用sendFinished,走mOrderedHint为true的那条线路,这里面mAbortBroadcast值得注意,如果为true,级别高的接收器收到广播后,级别低的就收不到广播了,好了,我们来看看finishReceiver,看这里函数你能知道动态的广播为什么可以循环起来

4.3.7 finishReceiver

文件:ActivityManagerService.java

    public void finishReceiver(IBinder who, int resultCode, String resultData,            Bundle resultExtras, boolean resultAbort, int flags) {        // Refuse possible leaked file descriptors        if (resultExtras != null && resultExtras.hasFileDescriptors()) {            throw new IllegalArgumentException("File descriptors passed in Bundle");        }        final long origId = Binder.clearCallingIdentity();        try {            boolean doNext = false;            BroadcastRecord r;            synchronized(this) {                BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0                        ? mFgBroadcastQueue : mBgBroadcastQueue;                r = queue.getMatchingOrderedReceiver(who);                if (r != null) {                    doNext = r.queue.finishReceiverLocked(r, resultCode,                        resultData, resultExtras, resultAbort, true);                }            }            if (doNext) {                // 处理下一条广播                r.queue.processNextBroadcast(false);            }            trimApplications();        } finally {            Binder.restoreCallingIdentity(origId);        }    }

首先判断是不是是前台广播还是后台广播,如果是后台广播则开始执行下一条广播,值得一提的是resultAbort和mAbortBroadcast上面的一致,最终的影响是这行代码:

if (r.receivers == null || r.nextReceiver >= numReceivers                        || r.resultAbort || forceReceive) {

4.4 scheduleReceiver处理静态广播

我们还是一步步来看,首先:
文件:ActivityThread.java

        public final void scheduleReceiver(Intent intent, ActivityInfo info,                CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,                boolean sync, int sendingUser, int processState) {            updateProcessState(processState, false);            ReceiverData r = new ReceiverData(intent, resultCode, data, extras,                    sync, false, mAppThread.asBinder(), sendingUser);            r.info = info;            r.compatInfo = compatInfo;            // 见4.4.1            sendMessage(H.RECEIVER, r);        }

4.4.1 H

文件:ActivityThread.java

        public void handleMessage(Message msg) {            switch (msg.what) {            ......                case RECEIVER:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");                    // 见4.4.2                    handleReceiver((ReceiverData)msg.obj);                    maybeSnapshot();                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;             ......

4.4.2 handleReceiver

文件:ActivityThread.java

    private void handleReceiver(ReceiverData data) {        unscheduleGcIdler();        String component = data.intent.getComponent().getClassName();        LoadedApk packageInfo = getPackageInfoNoCheck(                data.info.applicationInfo, data.compatInfo);        IActivityManager mgr = ActivityManagerNative.getDefault();        BroadcastReceiver receiver;        try {            java.lang.ClassLoader cl = packageInfo.getClassLoader();            data.intent.setExtrasClassLoader(cl);            data.intent.prepareToEnterProcess();            data.setExtrasClassLoader(cl);            // 用反射的方式生成BroadcastReceiver            receiver = (BroadcastReceiver)cl.loadClass(component).newInstance();        } catch (Exception e) {            data.sendFinished(mgr);            throw new RuntimeException(                "Unable to instantiate receiver " + component                + ": " + e.toString(), e);        }        try {            Application app = packageInfo.makeApplication(false, mInstrumentation);            ContextImpl context = (ContextImpl)app.getBaseContext();            sCurrentBroadcastIntent.set(data.intent);            receiver.setPendingResult(data);            // 调用目标Receiver的onReceive()            receiver.onReceive(context.getReceiverRestrictedContext(),                    data.intent);        } catch (Exception e) {            data.sendFinished(mgr);            if (!mInstrumentation.onException(receiver, e)) {                throw new RuntimeException(                    "Unable to start receiver " + component                    + ": " + e.toString(), e);            }        } finally {            sCurrentBroadcastIntent.set(null);        }        if (receiver.getPendingResult() != null) {            data.finish();        }    }

用反射的方法获得类,然后生成BroadcastReceiver,接着调用onReceive()方法

5 总结与建议

5.1 并行广播和串行广播的发送特点


这是发广播给动态注册接收器时的特点,采用异步的形式,广播之间不会互相干扰


这是采用串行发送广播的方式,采用的是同步的机制,根据优先级来发送,优先级高的receiver可以停止广播想优先级低的发送;静态注册的Receiver和有序的动态注册的Receiver均采用这个方式

5.2 广播处理的流程图


这张图展示了有序和无序广播的处理流程

5.3 广播处理的时序图

5.4 建议

  • 判断自己的所需要获取的广播是否能够动态注册获取,因为Google基于优化考虑,比如SCREEN_OFF或SCREEN_OFF已经不能通过静态注册来获取了

  • 不要在onReceiver中进行耗时的操作,如果必须要这样做,可以发送Intent启动一个service来做

  • 如果需要一直对广播保持监听,建议使用静态注册,因为静态注册就算是目标进程不在了也可以重启,而动态注册的Receiver的生命周期会受应用的影响,应用销毁了,Receiver也就收不到广播了

  • 如果只在同一APP内部发送和接收广播,将exported属性设置成false,或者可以使用LocalBroadcastManager类(本地广播)

  • 广播发送和接收建议带上权限

  • 如果在onReceive()中开了一个子线程来执行工作,会碰上onReceive()已经返回,而子线程还没有做完工作的情况,这时候如果AMS结束了进程,这时子线程也会挂掉,但是工作却没有做完,可以利用要PendingResult来规避这个问题,一般finish()方法一般都是PendingResult不等于null的时候调用(参考4.3.6),使用方法如下:

public void onReceive(final Context context, final Intent intent) {        //得到PendingResult        final PendingResult result = goAsync();          //放到异步线程中执行        AsyncHandler.post(new Runnable() {              @Override              public void run() {                  handleIntent(context, intent);//可进行一些耗时操作                  result.finish();              }          });      }

一旦调用goAsync(),那么BroadcastReceiver中的PendingResult将为null,这时finish方法得不到执行,AMS就收不到onReceive()执行完的消息,一直要到子线程调用result.finish()才会知道,这个目的只是为了不阻塞主线程,操作还是要在规定时间内完成

更多相关文章

  1. Android(安卓)得到手机的宽度和高度 Android(安卓)不同设备兼容
  2. Android(安卓)Studio Gradle配置
  3. Android通过rc启动三方可执行文件
  4. Android(安卓)JNI和NDK学习(2)--编程入门
  5. android 系统定制的小技巧
  6. [整]Android(安卓)SlidingMenu Demo 环境搭建
  7. Android:Native C code打印android log
  8. Android(安卓)dp方式的屏幕适配工具使用(Android(安卓)Studio插

随机推荐

  1. Android高手进阶教程(二)之----Android(
  2. Windows配置Android(安卓)SDK环境
  3. Android系统结构
  4. blcr加速android启动速度遇到的问题及解
  5. Android应用程序键盘(Keyboard)消息处理机
  6. Android(安卓)实现系统深度休眠笔记
  7. Android(安卓)Launcher 分析
  8. android中如何执行java命令
  9. Android(安卓)【手撕Glide】--Glide缓存
  10. Android多媒体应用使用MediaPlayer播放音