Android开发 | 广播机制
Android开发之简析Broadcast广播机制
Android开发之简析Broadcast广播机制
说起广播,笔者就想起了高中校园的课间音乐。
那时候,学校点播室会按时间表导入音乐文件,到对应时间段,学校广播链路就会播放导入的音频,这时所有安装了扬声器的教学单元都会同步接收播放信号,同时播放同学们投稿的音乐,并且这不是一次性的,这一周里每天对应的课间时间段,所有扬声器都会响应广播链路此时传递的音频信号。
高中三年,小编听过一整周的全课间时间段的仙剑奇侠传主题曲:忘记时间、偏爱、六月的雨、此生不换,生生世世爱;听到了好多年都没再听到过的月亮船;弗兰克上校的一支探戈的配乐一步之遥 Por una Cabeza;酷玩乐队的Viva La Vida、Something Just Like This、A Sky Full of Stars;速7主题曲See You Again,同歌手作品We Don't Talk Any More;陈雪凝的绿色;邹姐说好听的历历万乡。小编高一时点播了酷玩乐队的Yellow,但那个时间段每天都要去食堂吃饭没听到,曾暗恋过的女生那周每天中午问我:SK,你个老年人,听这么老的歌,你听到没有,你点的歌刚才放了,你今天听到没有,你怎么又没有听到啊?隔了一周,她托小编帮忙点歌,点的都是酷玩乐队的,后来得知她是酷玩的粉,小编:?
广播一个班一周只能点3首,室友和小编说也要点,但是小编答应3首都给女生,因为这件事和室友吵一架,因为这个女生,小编和室友吵过3次。那天晚自习她给小编扮鬼脸小编还傻笑,被班主任脸贴着窗看到,站在前门大骂了小编10分钟,小编内心感到很羞愧前去找班主任辞去班长之职。小编后来一顿蜜汁操作,被女生骂了整整两年的傻X,什么坏事都没有干的小编默默在教室走廊操场体育馆马路上承受了“傻X”这个跨越世纪,经久不衰的时代名词的屡次暴击。高考前些许日,环绕在广播声中,在灿烂的阳光下,在学校最宽阔的马路上,巧合让小编走在了女生身后,不知是什么使她回眸一笑,负伤的小编居然释怀了。
高中最好的朋友因女人被我扇了一耳光,素昧平生走到朝夕相处的室友退了学,不堪回首的过往,让我想起了Once Upon A Time in Amercia:兄弟如垫背黑一枪,女人如蛋糕揩一块,美国梦一场滑一跤,往事烟一口笑一笑。
笔者对于广播,理解深刻:thumbsdown ,希望读者也能借此理解什么是广播,了解如何在某个接收器接收到广播后就阻断广播的传播,了解如何把广播传播给指定的对象,了解如何让你优先接收到广播,了解如何让你初来乍到就能“点播”,了解如何让你随时都能发送和接收广播。下面就和笔者来体验一回广播,听一听广播机制的故事吧。
一、广播的类型
广播主要分为标准广播(Normal broadcasts
)和有序广播(Ordered broadcasts
)。
标准广播是异步执行的,通俗地讲就是一旦广播发出后,所有广播接收器都会同时收到该广播消息,不存在顺序性。

有序广播是顺序同步执行的,当广播发出后,同一时刻最多只能存在一个广播接收器接收该广播消息,且先接收到广播消息的接收器可以阻断广播消息以阻止广播消息的继续传递。

二、接收系统广播
Android系统内置了许多系统级别的广播,用户的程序可以接收这部分广播。比如系统时区切换时会唤醒部分应用的本地化服务、系统语言切换时会激活Google Services
相关的本地化服务更新,以及电池电量低时会导致相机调用闪光灯时提示“电量低,闪光灯无法使用。”等。
2.1 静态注册广播接收器
从Android Oreo(8.0)版本开始,Google对广播机制进行了较大修改,静态注册的广播接收器(隐式广播
)将无法正常接收广播消息,除非响应的是部分系统级别的广播。下面以开机启动广播android.intent.action.BOOT_COMPLETED
为例进行介绍。
首先新建一个类MyBootBCReceiver
使其继承于BroadcastReceiver
,重写onReceive()
方法:
|
|
然后在清单文件添加receiver
标签,添加intent
过滤器:
|
|
2.2 动态注册广播接收器
动态注册广播接收器是通过代码在程序中动态创建接收器对象(一般是活动的创建期),然后在清单文件中声明相关权限(访问系统网络状态需要网络权限),然后在活动结束时解除注册接收器。如果是在活动的onPause()
回调函数中创建的接收器实例,那么务必在onStop()
回调函数中解除注册它。上面两种动态注册和解除的时机均在活动的生命生成期的相对状态,这么做是为了避免该广播在其他生存期被其他不必要的活动的接收器接收,提高安全性。
此外,动态注册的广播接收器在接收同一广播时,总是优先于静态注册。
下面以监听系统网络变化为例。
|
|
在MainActivity
中新建了一个内部类NetworkChangeReceiver
,它继承于BroadcastReceiver
,重写该类的onReceive()
方法,通过ConnectivityManager
来获取网络信息。
在MainActivity
的onCreate()
方法中,创建一个IntentFilter
对象实例,为其添加动作android.net.conn.CONNECTIVITY_CHANGE
,这是说明为该Intent
过滤出含该动作的广播。
最后在清单文件中添加权限声明:
|
|
三、发送自定义广播
3.1 发送标准广播
《第一行代码》第二版是通过创建一个自定义广播接收器类,再于清单文件声明接收器与其intent
过滤器以指明要接收的广播。
|
|
由于《第一行代码》第二版是基于Android Nougat(7.0)讲授的,但Android O就不支持自定义隐式广播了。因此,如果仅通过在清单文件中申明接收器是无法让广播被接受到的。
上述自定义的广播无需在清单文件中声明,但需要对发送广播时的intent
指定接收对象,这个可以通过setPackage()
指定包名实现。此外,不要忘记动态注册的接收器需要在活动销毁时取消注册。
下面通过点击按钮发出广播com.cosyspark.bootBCReceiver.MY_BD
,并通过MyBD
的实例化对象接收广播,显示toast
。
代码如下:
|
|
3.2 发送有序广播
有序广播只需在标准广播的基础上,以sendOrderedBroadcast()
方法取代sendBroadcast()
方法。另外,可以对接收器的Intent
过滤器设置priority
优先级。优先级高(大)的广播将先收到广播,如果不设置优先级,广播的接收顺序将是随机的。
此外,在自定义的接收器中可以调用abortBroadcast()
方法,那么此接收器实例接受到广播信息后将会阻止其想其他接收器传播。
3.3 发送本地广播
标准广播和有序广播都是面向系统全局的,也就是说在发出广播的应用之外,其他应用内的活动也能接收到该广播,因此Android又提出了本地广播的概念。具体使用方法与上述方法大致相同,差别在于发送本地广播时是利用LocalBroadcastManager
类的内置方法sendBroadcast()
进行广播,注册监听器时是利用LocalReceiver类
的内置方法registerReceiver()
和unregisterReceiver()
进行的。
四、DEMO

