BroadcastReceiver的工作原理

107 阅读2分钟

「这是我参与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方法