IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 广播的注册和收发原理 -> 正文阅读

[移动开发]Android 广播的注册和收发原理

动态广播的注册和收发原理

广播的注册原理

  • 注册广播一般通过 Context 的 registerReceiver() 方法,通过一些列的简单调用 ,调用到了 registerReceiverInternal() 方法。
    private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
            IntentFilter filter, String broadcastPermission,
            Handler scheduler, Context context, int flags) {
            // IIntentReceiver 是一个 binder 对象,用来 IPC 传输用的
        IIntentReceiver rd = null;
        if (receiver != null) {
            if (mPackageInfo != null && context != null) {
                if (scheduler == null) {
                    scheduler = mMainThread.getHandler();
                }
                // 通过 getReceiverDispatcher 获取 IIntentReceiver
                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();
            }
        }
        	// 通过 AMS 调用注册函数 registerReceiver() 
            final Intent intent = ActivityManager.getService().registerReceiver(
                    mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                    broadcastPermission, userId, flags);
            return intent;
    }

registerReceiverInternal() 中,先创建了 binder 对象 IIntentReceiver ,然后通过 AMS 调用 registerReceiver() 来注册广播,下面看看是如何创建 IIntentReceiver 的。

  • getReceiverDispatcher()
	// 通过 BroadcastReceiver 和 context 对象 创建一个 IIntentReceiver 
    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) {
            	// 创建一个 ReceiverDispatcher 对象
                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();
        }
    }

getReceiverDispatcher() 中,通过 BroadcastReceiver 对象 和 Content 对象 创建了IIntentReceiver 对象,并存入到 Map 中,下次如果再获取直接从 Map 中返回。所以这里可以确定 一个 Content 和 BroadcastReceiver 同时来确定一个 IIntentReceiver 对象,也就是同一个Content对应不同的 BroadcastReceiver 会生成不同的 IIntentReceiver ,反之也一样。这和之前讲过 Service 的差不多。下面是 ReceiverDispatcher 的构造函数

  • ReceiverDispatcher 其构造函数引用了 BroadcastReceiver 对象的引用 ,同时还 new 了 InnerReceiver 对象。
        ReceiverDispatcher(BroadcastReceiver receiver, Context context,
                Handler activityThread, Instrumentation instrumentation,
                boolean registered) {
            if (activityThread == null) {
                throw new NullPointerException("Handler must not be null");
            }

            mIIntentReceiver = new InnerReceiver(this, !registered);
            mReceiver = receiver;
            mContext = context;
            mActivityThread = activityThread;
            // ... 
            mLocation.fillInStackTrace();
        }

InnerReceiver 对象就是 binder 对象,他引用了 ReceiverDispatcher 对象,

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

            InnerReceiver(LoadedApk.ReceiverDispatcher rd, boolean strong) {
                mDispatcher = new WeakReference<LoadedApk.ReceiverDispatcher>(rd);
                mStrongRef = strong ? rd : null;
            }
            
}

所以引用链如下: AMS -> IIntentReceiver -> ReceiverDispatcher -> BroadcastReceiver ;所以 AMS 可以通过这么一个引用调用到 BroadcastReceiver 的 onReceive() 函数。

  • 那么注册广播在 AMS 是怎么处理的?上面说过 registerReceiverInternal() 方法创建了 ReceiverDispatcher 后调用了 AMS 的 registerReceiver() 函数,
    public Intent registerReceiver(IApplicationThread caller, String callerPackage,IIntentReceiver receiver, IntentFilter filter,s) {
	
	// final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>();
	// mRegisteredReceivers 是一个 Map key 是传过来的 IIntentReceiver ,value 是 ReceiverList 是一个 IntentFilter 列表;
		ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
	
		if (rl == null) {
				// 创建一个 ReceiverList 为了之后匹配 intentFileter
                rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                        userId, receiver);
                if (rl.app != null) {
                    final int totalReceiversForApp = rl.app.receivers.size();
                    rl.app.receivers.add(rl);
                } 
                mRegisteredReceivers.put(receiver.asBinder(), rl);
            }
      BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                    permission, callingUid, userId, instantApp, visibleToInstantApps);
       rl.add(bf);
       mReceiverResolver.addFilter(bf);
    }

广播的发送原理

广播的发送一般通过 public void sendBroadcast(Intent intent) 方法发送
  • 调用到 ContextImpl 后方法如下
    @Override
    public void sendBroadcast(Intent intent) {
    	// 把 intent 传递给 AMS 
        ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                    getUserId());
    }
  • AMS 的 broadcastIntent()
    public final int broadcastIntent(IApplicationThread caller,Intent intent, 	...) {
        // 	.....
            int res = broadcastIntentLocked(callerApp,
                    callerApp != null ? callerApp.info.packageName : null,
                    intent, resolvedType, resultTo, resultCode, resultData, resultExtras,
                    requiredPermissions, appOp, bOptions, serialized, sticky,
                    callingPid, callingUid, userId);
            return res;
        }
    }

    final int broadcastIntentLocked(ProcessRecord callerApp,String callerPackage, Intent intent, ...){
    	// ......
    	
    	List<BroadcastFilter> registeredReceivers = null;
    	// 通过 intent 找到  registeredReceivers 列表
		registeredReceivers = mReceiverResolver.queryIntent(intent,resolvedType, false , userId);
		// ordered 是否是有序广播 动态广播默认是无序的
		if (!ordered && NR > 0) {
			// broadcastQueueForIntent 找到 BroadcastQueue ;
			// AMS 中有两个 BroadcastQueue ,一个是分发紧急任务的,一个是分发普通任务的,这里用的是普通任务
            final BroadcastQueue queue = broadcastQueueForIntent(intent);
            // 创建 BroadcastRecord 对象,内部有 registeredReceivers 列表
            BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,
                    callerPackage, callingPid, callingUid, callerInstantApp, resolvedType,
                    requiredPermissions, appOp, brOptions, registeredReceivers, resultTo,
                    resultCode, resultData, resultExtras, ordered, sticky, false, userId);
         
            if (!replaced) {
            	// 把创建的 BroadcastRecord 添加到 queue 的并行分发的列表 ;
                queue.enqueueParallelBroadcastLocked(r);
                // 调用 scheduleBroadcastsLocked() 开始准备分发广播
                queue.scheduleBroadcastsLocked();
            }
            registeredReceivers = null;
            NR = 0;
        }
	}
  • 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 调用到了 processNextBroadcast(true); 方法 ,然后又调用了 processNextBroadcastLocked(fromMsg, false); fromMsg 为 true

  • processNextBroadcastLocked(true, false);
	// 找到动态广播分发的部分就行
    final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {

		BroadcastRecord r;
		// while 循环不断从 mParallelBroadcasts 列表中取出 BroadcastRecord 
		while (mParallelBroadcasts.size() > 0) {
            r = mParallelBroadcasts.remove(0);
            r.dispatchTime = SystemClock.uptimeMillis();
            r.dispatchClockTime = System.currentTimeMillis();
			
            final int N = r.receivers.size();
            // BroadcastRecord 中有一个 receivers 列表 通过 循环一次去除 receiver
            for (int i=0; i<N; i++) {
                Object target = r.receivers.get(i);
                // 调用deliverToRegisteredReceiverLocked 继续分发 
                // 其内部调用了  performReceiveLocked(filter.receiverList.app,)方法
                deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false, i);
            }
        }
		// .....

	}

performReceiveLocked() 到这就是广播的接收原理了

广播的接收原理


    void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver, Intent intent, ) throws RemoteException {
        if (app != null) {
            if (app.thread != null) {
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);
            } 
        } else {
            receiver.performReceive(intent, resultCode, data, extras, ordered,
                    sticky, sendingUser);
        }
    }

上面的方法:如果 app.thread != null 不为 null ,则调用了 app.thread.scheduleRegisteredReceiver 方法,而他也直接引用了 receiver 这个 binder 对象,只有当 app.thread == null 的时候才会这么调用。目的是为了让所有进程广播尽量的串行调用。scheduleRegisteredReceiver 内部也是调用的 receiver.performReceiv() 函数

        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);
        }
  • IIntentReceiver 之前创建的时候他的实现类是 ReceiverDispatcher 的内部类 InnerReceiver 那么看一下它的 performReceive 方法。
            @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) {
                    rd = null;
                } else {
                    rd = mDispatcher.get();
                }
                if (rd != null) {
					// 获取到 ReceiverDispatcher 后 调用其 performReceive
                    rd.performReceive(intent, resultCode, data, extras,
                            ordered, sticky, sendingUser);
                } else {
                    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();
                    }
                }
            }
        }

这个方法就是获取到 ReceiverDispatcher 对象后调用了 performReceive 方法

  • 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) {
            } else {
                if (ActivityThread.DEBUG_BROADCAST) {
                    int seq = intent.getIntExtra("seq", -1);
                }
            }
            // post 到了 mActivityThread 中
            if (intent == null || !mActivityThread.post(args.getRunnable())) {
                 // 。。。
            }
        }

performReceive 中,创建了 Args 对象,其内部有一个 runnable 对象,然后把它 post 到了 mActivityThread 中,所以广播执行的 runnable 方法是在主线程调用的。

  • Args getRunnable()
public final Runnable getRunnable() {
                return () -> {
                 // 他在 ReceiverDispatcher 的内部类中 所以可以拿到 mReceiver 
                    final BroadcastReceiver receiver = mReceiver;
                  	// ...
                    try {
                        ClassLoader cl = mReceiver.getClass().getClassLoader();
                        intent.setExtrasClassLoader(cl);
                        intent.prepareToEnterProcess();
                        setExtrasClassLoader(cl);
                        receiver.setPendingResult(this);
                        // 执行 onReceive 方法
                        receiver.onReceive(mContext, intent);
                    } 

                    if (receiver.getPendingResult() != null) {
                    	// ????? 
                        finish();
                    }
                };
            }
  • finish()
        public final void finish() {
        	// TYPE_COMPONENT 代表是静态广播
            if (mType == TYPE_COMPONENT) {
                final IActivityManager mgr = ActivityManager.getService();
                if (QueuedWork.hasPendingWork()) {
                    QueuedWork.queue(new Runnable() {
                        @Override public void run() {
                        // 告诉 AMS 广播已经执行完了
                            sendFinished(mgr);
                        }
                    }, false);
                } else {
                 // // 告诉 AMS 广播已经执行完了
                    sendFinished(mgr);
                }
            } else if (mOrderedHint && mType != TYPE_UNREGISTERED) {
            	// 动态广播 如果满足条件也需要 告诉 AMS 广播已经执行完了
                final IActivityManager mgr = ActivityManager.getService();
                sendFinished(mgr);
            }
        }

小结

	对于普通的动态广播,AMS 是并行分发的 ,但是到了客户端就会串行分发了

在这里插入图片描述

静态广播的注册和收发原理

广播的注册原理

  • 和动态广播不一样,静态广播的注册是在 AndroidManifest.xml 中配置的。之前讲过,在 SystemServer 启动后执行的 run 方法中,启动了 PackageManagerService ,在 PMS 中解析了每个安装包的 AndroidManifest 文件,代码从创建 PMS 的构造函数为起点,调用到了 PackageParse.java 中的 parseBaseApplication() 函数,其中有下面的代码:
else if (tagName.equals("receiver")) {
				// parseActivity 解析 XML 的配置
                Activity a = parseActivity(owner, res, parser, flags, outError, cachedArgs,
                        true, false);
                // 	.... 
                // 解析完成后加入到 receivers 列表中,用的时候再去这个列表中查询就可以了。
                owner.receivers.add(a);

            }

通过 parseActivity() 函数,解析 xml 的数据,返回了 Activity 对象,这个 Activity 不是 UI 那个Activity,只是一个普通组件。解析完成后加入到 receivers 列表中,需要使用的时候到里面去查。

广播的分发原理

  • context 的 sendBroadcast()
    @Override
    public void sendBroadcast(Intent intent) {
    	// 会调用到 AMS 的 broadcastIntent() 函数
        ActivityManager.getService().broadcastIntent(
                    mMainThread.getApplicationThread(), intent, resolvedType, null,
                    Activity.RESULT_OK, null, null, null, AppOpsManager.OP_NONE, null, false, false,
                    getUserId());
    }

sendBroadcast() 函数会调用到 AMS 的 broadcastIntent() 其内部又调用了 broadcastIntentLocked() 函数

final int broadcastIntentLocked(ProcessRecord callerApp,...{
		// .....
		// Figure out who all will receive this broadcast.
    	List receivers = null; // 静态广播列表
    	List<BroadcastFilter> registeredReceivers = null; // 动态广播列表
   		// 查找出有哪些 receiver 可以接收这个广播
   		// 先查找出 静态广播
		receivers = collectReceiverComponents(intent, resolvedType, callingUid, users);
		// 查找动态广播
		 List<BroadcastFilter> registeredReceiversForUser =
                            mReceiverResolver.queryIntent(intent,
                                    resolvedType, false /*defaultOnly*/, users[i]);
        if (registeredReceivers == null) {
                        registeredReceivers = registeredReceiversForUser;
                    } else if (registeredReceiversForUser != null) {
                        registeredReceivers.addAll(registeredReceiversForUser);
                    }
	    if (!ordered && NR > 0) {
	        // 处理动态 service 并加入到并行分发队列
            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);
            final boolean replaced = replacePending
                    && (queue.replaceParallelBroadcastLocked(r) != null);
            if (!replaced) {
            	// 加入到并行分发队列 
                queue.enqueueParallelBroadcastLocked(r);
                // 开始分发广播
                queue.scheduleBroadcastsLocked();
            }
            registeredReceivers = null;
            NR = 0;
        }
        // 处理剩下的 receive 加入到串行队列中
         if ((receivers != null && receivers.size() > 0){
          final BroadcastQueue queue = broadcastQueueForIntent(intent);
           		BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp,)
                queue.enqueueOrderedBroadcastLocked(r);
                queue.scheduleBroadcastsLocked();
		}
		
		return ActivityManager.BROADCAST_SUCCESS;
}

queue.scheduleBroadcastsLocked(); 分发广播和动态广播那一养走到了 processNextBroadcastLocked() 函数,但是函数内部处理静态广播比较复杂,因为它是串行的,要等待各种事件的返回才能开始下一个广播的发送。

	先处理并行分发的广播(上面已经讲过)
	如果有 pending广播,就直接返回,等待应用进程启动
	如果广播分发超时,废弃这个广播,处理下一个
	如果没有超时,正在分发中,则先返回等待
	如果当前广播分发完了一个receiver,进行下一个
	如果是动态注册的,直接分发(动态注册说明进程已经启动了)
	如果是静态注册的,先看进程是否启动了
	如果进程启动了直接分发,如果未启动则线启动进程,将广播设置成 pending 状态
	进程启动后 attachApplication 的时候处理这个 pending 广播
  • processNextBroadcastLocked
    final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {
        BroadcastRecord r;
        // 这里是处理并行广播的 上面讲过
        while (mParallelBroadcasts.size() > 0) {
        }
        do {
            if (mOrderedBroadcasts.size() == 0) {
                // 如果串行列表没有数据直接 return
                return;
            }
            // 取出列表第0个数据
            r = mOrderedBroadcasts.get(0);
            long now = SystemClock.uptimeMillis();
            // long dispatchTime;      // when dispatch started on this set of receivers
            // dispatchTime 是开始分发的时间
            // 判断是否超时了
            if ((numReceivers > 0) && (now > r.dispatchTime + (2 * mTimeoutPeriod * numReceivers))) {
                // forcibly finish this broadcast
                broadcastTimeoutLocked(false);
                forceReceive = true;
                // 设置 state 为 IDLE
                r.state = BroadcastRecord.IDLE;
            }
            // 如果 != BroadcastRecord.IDLE 代表正在分发呢 等着分发完
            if (r.state != BroadcastRecord.IDLE) {
                return;
            }
            // forceReceive 在刚才超时那设置成了 true
            if (r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) {
                cancelBroadcastTimeoutLocked();
                // 	。。。
                // 移除第一个
                mOrderedBroadcasts.remove(0);
                r = null;
                looped = true;
                // 结束本次循环开始下一次
                continue;
            }
			// 。。。 继续下面的逻辑在后面
        }
    }

broadcastTimeoutLocked() 是如何处理超时的

	final void broadcastTimeoutLocked(boolean fromMsg) {
		BroadcastRecord r = mOrderedBroadcasts.get(0);
		Object curReceiver;
        if (r.nextReceiver > 0) {
            curReceiver = r.receivers.get(r.nextReceiver-1);
            r.delivery[r.nextReceiver-1] = BroadcastRecord.DELIVERY_TIMEOUT;
        } else {
            curReceiver = r.curReceiver;
        }
        // mPendingBroadcast == r 意思是等待中超时了
        if (mPendingBroadcast == r) {
        // 设置成 null 反之 mPendingBroadcast 有赋值 下次循环遇到 mPendingBroadcast 直接返回了
            mPendingBroadcast = null;
        }
	    // Move on to the next receiver.
	    // 重制广播的状态
        finishReceiverLocked(r, r.resultCode, r.resultData,
                r.resultExtras, r.resultAbort, false);
        // 再调度一次广播的处理
        scheduleBroadcastsLocked();
		// ANR
		mHandler.post(new AppNotResponding(app, anrMessage));
	}
  • 超时过后会继续下一步 看 processNextBroadcastLocked 方法下一步
final void processNextBroadcastLocked(boolean fromMsg, boolean skipOomAdj) {

        // 判断超时后 代表当前是 IDEL 状态 没有正在分发的广播
        // Get the next receiver...
        // 获取下一个 receiver 
        int recIdx = r.nextReceiver++;
        // 设置广播时间戳
        r.receiverTime = SystemClock.uptimeMillis();
        if (recIdx == 0) {
            r.dispatchTime = r.receiverTime;
            r.dispatchClockTime = System.currentTimeMillis();

        }
        // 如果没有超时消息 则发送一条超时消息 postDelay了一个 runnable 超时了就会执行
        if (!mPendingBroadcastTimeoutMessage) {
            long timeoutTime = r.receiverTime + mTimeoutPeriod;
            setBroadcastTimeoutLocked(timeoutTime);
        }
        // 根据 receivers 列表取出下一个
        final Object nextReceiver = r.receivers.get(recIdx);
        // 判断是不是动态 receiver 动态receiver 代表进程还在 直接分发
        if (nextReceiver instanceof BroadcastFilter) {
            BroadcastFilter filter = (BroadcastFilter) nextReceiver;
            // 直接分发
            deliverToRegisteredReceiverLocked(r, filter, r.ordered, recIdx);
            return;
        }


        // 静态的 receiver
        // 先获取进程
        ProcessRecord app = mService.getProcessRecordLocked(targetProcess, info.activityInfo.applicationInfo.uid, false);

        r.state = BroadcastRecord.APP_RECEIVE;
        if (app != null && app.thread != null && !app.killed) {
            // 如果进程已经启动了 调用processCurBroadcastLocked 处理广播
            processCurBroadcastLocked(r, app, skipOomAdj);
            return;
        }
        // 如果进程没有启动 则启动进程
        if ((r.curApp = mService.startProcessLocked(targetProcess, ) {
            // 。。。。
            return;
        }
        // 设置 mPendingBroadcast 等带进程启动调用
        mPendingBroadcast = r;
        mPendingBroadcastRecvIndex = recIdx;

    }


广播的接收原理

  • 广播的发送那块将了 deliverToRegisteredReceiverLocked() 是分发动态 receiver 的函数,看看发送过后是怎么接收的
    private void deliverToRegisteredReceiverLocked(BroadcastRecord r,
                                                   BroadcastFilter filter, boolean ordered, int index) {
		// 调用 performReceiveLocked() 函数
        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) {
            //	ordered 为串行分发的 将状态设置成 CALL_DONE_RECEIVE 
            r.state = BroadcastRecord.CALL_DONE_RECEIVE;
        }
    }
  • performReceiveLocked()
    void performReceiveLocked(ProcessRecord app, IIntentReceiver receiver,...) throws RemoteException {
        if (app != null) {
            if (app.thread != null) {
                	// 调用了 app.thread.scheduleRegisteredReceiver 执行到了应用端
                    app.thread.scheduleRegisteredReceiver(receiver, intent, resultCode,
                            data, extras, ordered, sticky, sendingUser, app.repProcState);
              
            } 
        } 
    }
  • app.thread.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);
            // receiver 是 IIntentReceiver ,之前讲过 发送广播时,因为 ReceiverDispatcher 不能直接 IPC 传输
            // 所以 通过 ReceiverDispatcher类的内部类InnerReceiver 封装成了binder 对象。
            // 所以 receiver.performReceive 调用到的是 InnerReceiver 的 performReceive 方法,因为 InnerReceiver 引用了 ReceiverDispatcher ,performReceive 调用到了ReceiverDispatcher 的 performReceive 方法。
            receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
                    sticky, sendingUser);
        }

receiver 是 IIntentReceiver ,之前讲过 发送广播时,因为 ReceiverDispatcher 不能直接 IPC 传输,所以 通过 ReceiverDispatcher类的内部类InnerReceiver 封装成了binder 对象。所以 receiver.performReceive 调用到的是InnerReceiver 的 performReceive 方法,因为 InnerReceiver 引用了 ReceiverDispatcher ,performReceive 调用到ReceiverDispatcher 的 performReceive 方法。

  • 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 || !mActivityThread.post(args.getRunnable())) {
                if (mRegistered && ordered) {
                    IActivityManager mgr = ActivityManager.getService();
                    args.sendFinished(mgr);
                }
            }
        }

执行了 mActivityThread.post(args.getRunnable()) ,看看 runnable 执行内容

           public final Runnable getRunnable() {
                return () -> {
                    final BroadcastReceiver receiver = mReceiver;
                    final boolean ordered = mOrdered;
                    final IActivityManager mgr = ActivityManager.getService();
                    final Intent intent = mCurIntent;
                    mCurIntent = null;
                    mDispatched = true;
                    mPreviousRunStacktrace = new Throwable("Previous stacktrace");
                    if (receiver == null || intent == null || mForgotten) {
                        if (mRegistered && ordered) {
                            sendFinished(mgr);
                        }
                        return;
                    }
                    try {
                        ClassLoader cl = mReceiver.getClass().getClassLoader();
                        intent.setExtrasClassLoader(cl);
                        intent.prepareToEnterProcess();
                        setExtrasClassLoader(cl);
                        receiver.setPendingResult(this);
                        // 调用 onReceive 方法回调
                        receiver.onReceive(mContext, intent);
                    } 
                    if (receiver.getPendingResult() != null) {
                    	// 通知 AMS 广播分发完了,然后 AMS 就可以继续分发下一个 receiver 了
                        finish();
                    }
                };
            }
        }

Runnable 中主要执行了 onReceive 回调,然后通知 AMS 当前分发完成, AMS 可以继续分发下一个了,调用 AMS 的 am.finishReceiver() 方法

  • AMS 的 finishReceiver()
    public void finishReceiver(IBinder who, int resultCode, String resultData,
            Bundle resultExtras, boolean resultAbort, int flags) {

        final long origId = Binder.clearCallingIdentity();
        try {
            boolean doNext = false;
            BroadcastRecord r;

            synchronized(this) {
                BroadcastQueue queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                        ? mFgBroadcastQueue : mBgBroadcastQueue;
                        // 先找到 BroadcastRecord() 
                r = queue.getMatchingOrderedReceiver(who);
                if (r != null) {
                	// 然后调用 finishReceiverLocked() 重制广播属性
                	// 返回的 doNext 的条件之一就是之前提到的  r.state = BroadcastRecord.CALL_DONE_RECEIVE;
                	// 如果是这个 doNext = true 则可以进行下一个 广播的处理
                	// 串行分发的动态receiver 分发完的状态是 CALL_DONE_RECEIVE ,静态receiver状态APP_RECEIVE
                    doNext = r.queue.finishReceiverLocked(r, resultCode,
                        resultData, resultExtras, resultAbort, true);
                }
                if (doNext) {
                	// 分发下一个 receiver
                    r.queue.processNextBroadcastLocked(/*fromMsg=*/ false, /*skipOomAdj=*/ true);
                }
            }
        }
    }

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:09:06  更:2022-10-31 12:11:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 23:49:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码