一、广播的注册过程
1、静态注册过程
在Androidmanifest中进行注册,在receiver中加入关键字<intent-filter>:
<application > <receiver android:name=".MyBroadcastReceiver" android:exported="true"> <intent-filter> <action android:name="com.unknow.jason.broadcasttest.MY_BROADCAST"/> </intent-filter> </receiver> </application>
2、动态注册过程:
在Java代码中进行手动添加广播注册
intentFilter = new IntentFilter(); intentFilter.addAction("com.unknow.jason.broadcasttest.MY_BROADCAST"); myBroadcastReceiver = new MyBroadcastReceiver(); registerReceiver(myBroadcastReceiver, intentFilter); unregisterReceiver(myBroadcastReceiver);
3、两个主要的类的广播可以用来接收。
1).普通广播:(使用 Context.sendBroadcast发出)是完全异步的。所有接收者都运行在一个未定义的顺序里,有时甚至同时接收。这很高效,但也意味着不能使用结束或暂停API。
2).有序广播:(使用 Context.sendOrderedBroadcast发出)同一时间只传递一个接收器。每个接收器依次执行,它可以传送结果到下一个接收器,当然也可以暂停传送。这个顺序在android:priority属性里通过 intent-filter定义,如果定义同样的优先级则是随机顺序
4、广播注册流程
1)动态注册过程。
在整个注册过程中,先从activity-> ContextWrapper.registerReceiver() ->ContextImpl.registerReceiver() -> 获取handler ->loadApk -> ActivityManagerService中进行注册.
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (rl == null) { rl = new ReceiverList(this, callerApp, callingPid, callingUid, userId, receiver); if (rl.app != null) { rl.app.receivers.add(rl); } else { receiver.asBinder().linkToDeath(rl, 0); rl.linkedToDeath = true; } mRegisteredReceivers.put(receiver.asBinder(), rl); } BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage, permission, callingUid, userId); rl.add(bf); mReceiverResolver.addFilter(bf); ... return sticky;
核心注册的地方是在ActivityManagerService中:把广播接收器receiver保存一个ReceiverList列表中,这个列表的宿主进程是rl.app,这里就是MainActivity所在的进程了,在ActivityManagerService中,用一个进程记录块来表示这个应用程序进程,它里面有一个列表receivers,专门用来保存这个进程注册的广播接收器。接着,又把这个ReceiverList列表以receiver为Key值保存在ActivityManagerService的成员变量mRegisteredReceivers中,这些都是为了方便在收到广播时,快速找到对应的广播接收器的。最后把广播接收器receiver和filter关联起来并保存到AMS的成员mReceiverResolver里。
2)静态注册过程
静态注册是在每个应用的AndroidManifest.xml中进行定义。静态注册的广播最后保存在PMS(Package Manage Service)中的receiver列表中,在查询时是由AMS去PMS查找该广播,查到后再由AMS交给用户处理。
5、广播接收流程
下图为广播的发送流程图:
在整个的发送流程中可以大致分成三个部分:
1) 从MainActivity -> ActivityManagerService这个过程,通过自己的sendBroadcast把一个广播通过Binder进程间通信机制发送给AMS,AMS根据这个广播的Action类型找到相应的广播接收器,然后把这个广播放进自己的消息队列BroadQueue中去。
2) 从Handler -> Handler, 由于广播的的发送和处理是异步的(否则长时间的处理容易出现ANR),这里处理异步操作主要体现在两个handler的作用,第一个handler是接收AMS发送过来的广播,然后AMS就可以直接返回去处理下一个广播, 然后在收到这个广播后
会去检查广播发送和接收的权限,如果权限不符合则直接返回。最后进入到LoadApk.ReceiverDispatcher,这里的ReceiverDispatcher就是之前mainActivity在注册的时候写入的,这样就找到了对应需要接收的activity。
再通过第二个handler进行广播分发给对应的Activiy,然后自己返回继续处理下一个广播。
所以这里通过两个handler对广播分发和查找对应接收器来达到异步效果。
3) 最后这个广播进入到activity的onReceiver函数中处理。整个广播发送阶段结束