BroadcastReceiver 工作过程
主要分为两个部分:广播注册、广播发送/接收
简单回顾广播使用方法
先定义广播接收者
public class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context,Intent intent){
String action = intent.getAction();
// do some works
}
}
接着注册广播接受者(静态)
<receiver android:name = ".MyReceiver">
<intent-filter>
<action android:name = "com.ryg.receiver.LAUNCH">
</intent-filter>
</receiver>
动态注册
IntentFilter filter = new IntentFilter();
filter.addAction("com.ryg.receiver.LAUNCH");
registerReceiver(new MyReceiver(),filter);
发送广播
Intent intent = new Intent();
intent.setAction("com.ryg.receiver.LAUNCH");
sendBrodcast(intent);
BroadcastReceiver注册过程
静态广播在应用安装时由系统自动完成注册,具体来说是由PMS(Package Manager Service)来完成注册过程的。另外三大组件也是如此。
而动态注册过程是从ContextWrapper的registerReceiver方法开始,和Activity以及Service一样。
而ContextWrapper将注册交给了ContextImpl来完成。
而ContextImpl的registerReceiver又调用了registerReceiverInternal
从mPackgeInfo获取IIntentReceiver对象,然后再采用跨进程的方式向AMS发送广播注册请求。之所以使用IIntentReceiver对象,而不是BroadcastReceiver。
因为这个注册过程是进程间通信的过程,而BroadcastReceiver不能直接跨进程传递,需要依赖IIntentReceiver来中转一下。
而IIntentReceiver必须是个Binder接口,其具体实现是LoadedApk.ReceiverDispatcher.
InnerReceiver。
而ReceiverDispatcher的内部同时保存了BroadcastReceiver和InnerReceiver,使得当ReceiverDispatcher收到广播后,可以调用BroadcastReceiver的onReceive。
ReceiverDispatcher 的getReceiverDispatcher 在上面的代码中被调用了,getReceiverDispatcher重新创建了一个ReceiverDispatcher,并返回其保存的InnerReceiver
注册广播的主要实现在AMS中,即ActivityManagerNative,保存远程的InnerRecevier和IntentFilter。
广播的发送和接收
广播的发送和接收本质是一个过程的两个阶段。
广播的发送仍然开始于ContextWrapper的sendBroadcast方法,之所以不是Context,是因为Context的sendBroadcast是一个抽象方法。和广播注册过程一样,ContextWrapper的sendBroadcast将事情交给ContextImpl去处理,而ContextImpl直接对AMS发起了异步请求。
调用的broadcastIntent,其中关键是调用了broadcastIntentLocked。
//表明广播是否要对处于停止状态的应用起作用。
//FLAG_EXCLUDE_STOPPED_PACKAGES和EXCLUDE_STOPPED_PACKAGES
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKGES)
broadcastIntentLocked内部会根据intent-filter查找出匹配的广播接收者并经过一系列的条件过滤,最终会将满足条件的广播接收者添加到BroadcastQueue中,接着BroadcastQueue就会将广播发送给相应的广播接收者。
broadcastIntentLocked在将广播接收者加入queue后,还调用了BroadcastQueue的scheduleBroadcastsLocked。但scheduleBroadcastsLocked也不是立刻发送广播,他发送了一个BROADCAST_INTENT_MSG类型消息,BroadcastQueue收到消息后会调processNextBroadcast方法。
processNextBroadcas:
系统遍历存储着无序广播的mParallelBroadcasts,并将其中的广播发送给它们所有的接收者,而这个发送过程由performReceiveLocked方法来完成,它负责将一个广播发送给一个特定的接收者。
performReceiveLocked如下,主要是通过app.thread调起应用程序接受广播
ApplicationThread的scheduleRegisteredReceiver通过InnerReceiver的performReceive实现广播接收。
创建了一个Args对象并通过mActivityThread的post方法来执行Args中的逻辑,而Args实现了Runnable接口。mActivityThread是一个handler,它其实就是ActivityThread的内部类H类型mH。
Args的run方法中有这几行代码: