Android(安卓)广播内部机制详解(三)
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()才会知道,这个目的只是为了不阻塞主线程,操作还是要在规定时间内完成
更多相关文章
- Android(安卓)得到手机的宽度和高度 Android(安卓)不同设备兼容
- Android(安卓)Studio Gradle配置
- Android通过rc启动三方可执行文件
- Android(安卓)JNI和NDK学习(2)--编程入门
- android 系统定制的小技巧
- [整]Android(安卓)SlidingMenu Demo 环境搭建
- Android:Native C code打印android log
- Android(安卓)dp方式的屏幕适配工具使用(Android(安卓)Studio插