「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。
BroadcastReceiver的工作原理
首先回顾一下一般的BroadcastReceiver的使用
首先定义一个广播接收器
class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
}
}
接着可以使用动态注册或者静态注册
静态在主配置文件配置
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="xxxxxxx"/>
</intent-filter>
</receiver>
动态配置
IntentFilter filter = new IntentFilter();
filter.addAction("xxxx");
registerReceiver(new MyReceiver(),filter);
静态注册其实在app安装时,由PMS(PackageManagerService)来注册(四大组件都是如此),但是动态注册一般需要借助AMS(ActivityManagerService)来注册,这点在之前Activity和Service的创建过程中已经体现出来了。
动态注册过程
和Activity和Service一样的,都是从ContextWrapper开始与AMS进行跨进程通信(通过Binder机制),显然需要将一个Binder接口传给AMS,这个Binder接口叫做IIntentReceiver,同时为了能够回调onReceive方法和Service类似这里使用了一个ReceiverDispatcher将IIntentReceiver和原BroadCastReceiver包装起来。之所以不直接用BroadCastReceiver是因为BroadCastReceiver本身并不是一个Binder接口
AMS将IIntentReceiver接口和filter拿到之后将其存储起来后就完成了BroadCastReiver的注册。
AMS相关的方法原型为:
registerRecever(IApplicationThread caller,String callerPackage,IIntentReceiver receiver,IntentFilter filter,String permission,int userId)
发送和接收过程
同样也是类似的,ContextWrapper将任务交给AMS去完成,AMS首先通过标志FLAG_EXCLUDE_STOPPER_PACKAGES来判断是否要将广播发送给已经停止运行的应用,如果需要将广播发送给停止的应用,那么在Intent中添加FLAG_INCLUDE_STOPPED_PACKAGES标志即可,之后,AMS会根据filter查找相匹配的BroadReceiver,并加入BroadcastQueue队列,BroadcastQueue发送给对应的应用程序,和之前谈过的组件一样,也是拿到对应的IApplicationThread,然后将广播发送给这个应用。
IApplicationThread对应的接口方法原型为:
public void scheduleRegisteredReceiver(IIntentReceiver receiver,Intent intent,int resultCode,String dataStr,Bundle extras ,boolean ordered,boolean sticky,int sendingUser,int processState)throws RemoteException
在这个方法中将参数进一步加工处理后通过handler交给具体的线程处理并执行接口中的onReceive方法