
- Android里广播的分类
- 程序A能否接收到程序B的广播
- 广播注册的方式,并简单描述其区别
Broadcast的定义
Broadcast Receiver是Android四大组件之一,是全局大喇叭,就像以前学校里面的大喇叭一样,有什么事情,就通过广播通知到全校师生。Android的广播机制是一种广泛运用的在应用程序之间传输信息的机制。主要有两大角色:广播接收者和广播发送者。因此,我们可以注册一个广播接收者,用来接收其他进程或者系统发出的广播;同样的,我们也可以通过广播发送者,向其他进程发送我们的广播,告诉其他进程需要做某个动作。
Broadcast的注册方式
通过了解Broadcast的注册方式,是了解BroadcastReceiver的用法是最直接有效的,有静态注册和动态注册两种方法。
静态注册
在AndroidManifest.xml清单文件里直接声明的方式叫做静态注册。
1 | <receiver |
同时附上其他receiver的属性说明:
1 | <receiver |
然后重新onReceive()函数。
1 | public class mXRReceiver extends BroadcastReceiver { |
如上面代码,此时注册了mXRReceiver这个广播,当系统启动后,就会发送BOOT_COMPLETED的广播,符合mXRReceiver所设置的过滤条件,就会自动调用onReceive()函数,执行对应内容。
注意:onReceive()函数不能执行耗时流程。
动态注册
所谓动态注册,就是代码运行到了才注册广播。具体如下:
1 | private void initBroadcastReceiver() { |
动态广播最好在Activity的onResume()注册、onPause()注销。一旦忘记注销,那么就会造成内存泄露哦。
静态/动态注册的区别
- 静态注册不受app是否运行所影响,即使app没有运行,app里静态注册的广播接收者也可以接收广播,因此比较耗电,占内存。适合长时间监听广播,如系统广播。
- 动态注册的广播在组件结束之前,也会随之结束(当然是手动注销的),适合只在特殊时刻监听广播。
- 动态注册的优先级高于静态广播。
Broadcast的分类
广播主要分为以下5个类型:
- 普通广播(Normal Broadcast)
- 系统广播(System Broadcast)
- 有序广播(Ordered Broadcast)
- 粘性广播(Sticky Broadcast)
- 本地广播(Local Broadcast)
普通广播
也就是标准广播,是一种完全异步执行的广播,和学校大喇叭完全一样,发出广播后,所有广播接收者都能收到广播,且没有优先之分,上面程序都是普通广播。
系统广播
可以理解为安卓源码里面已经存在的广播,一般只要涉及系统基础操作的,都会有对应的系统广播,现列举如下:
监听网络变化 | android.net.conn.CONNECTIVITY_CHANGE |
关闭或打开飞行模式 | Intent.ACTION_AIRPLANE_MODE_CHANGED |
充电时或电量发生变化 | Intent.ACTION_BATTERY_CHANGED |
电池电量低 | Intent.ACTION_BATTERY_LOW |
电池电量充足(即从电量低变化到饱满时会发出广播 | Intent.ACTION_BATTERY_OKAY |
系统启动完成后(仅广播一次) | Intent.ACTION_BOOT_COMPLETED |
按下照相时的拍照按键(硬件按键)时 | Intent.ACTION_CAMERA_BUTTON |
屏幕锁屏 | Intent.ACTION_CLOSE_SYSTEM_DIALOGS |
设备当前设置被改变时(界面语言、设备方向等) | Intent.ACTION_CONFIGURATION_CHANGED |
插入耳机时 | Intent.ACTION_HEADSET_PLUG |
未正确移除SD卡但已取出来时(正确移除方法: | |
设置–SD卡和设备内存–卸载SD卡) | Intent.ACTION_MEDIA_BAD_REMOVAL |
插入外部储存装置(如SD卡) | Intent.ACTION_MEDIA_CHECKING |
成功安装APK | Intent.ACTION_PACKAGE_ADDED |
成功删除APK | Intent.ACTION_PACKAGE_REMOVED |
重启设备 | Intent.ACTION_REBOOT |
屏幕被关闭 | Intent.ACTION_SCREEN_OFF |
屏幕被打开 | Intent.ACTION_SCREEN_ON |
关闭系统时 | Intent.ACTION_SHUTDOWN |
重启设备 | Intent.ACTION_REBOOT |
有序广播
有序广播是一种同步执行的广播,按广播接收者的优先级由高到低排序,轮流接收到广播,且前面的广播接收者可以拦截该广播,这样后面的广播接收者就无法接收到该广播了。同时,前面的广播接受者也可以修改该广播并不做拦截,这样下一个接收到的广播就是被修改过的。 设置广播接收者的优先级可以用priority属性,数字越高代表优先级越高,最高是1000.
1 | <receiver |
使用起来,和普通广播仅差别在发送函数。普通广播sendBroadcast(intent),有序广播使用 sendOrderedBroadcast(intent);
本地广播
BroadcastReceiver可用于不同应用之间传递消息,但难免会出现这两种情况:
- 我们的App注册了广播接收者A,同时其他App可能要完成某个操作,碰巧发送了符合接收者A过滤条件的广播,导致我们的App就一直错误的接收到了这个广播;
- 我们的App注册了广播接收者A,同时其他App也碰巧注册了和我们同样过滤条件的广播接收者,这样就导致本来是我们App接收的广播,其他App也接收到了;
基于这两大问题,LocalBroadcastManager就可以很好的解决该问题。LocalBroadcastManager用于应用内部传递消息,比broadcastReceiver更加高效和安全。
为何更加高效安全
BroadcastReceiver是以 Binder 通讯方式为底层实现的机制不同,众所周知Binder是跨进程的。而LocalBroadcastManager 是利用应用内部的Handler来实现,只是利用到了 IntentFilter 的 match 功能,因为是 Handler 实现的应用内的通信,自然安全性更好,效率更高。
如何实现本地广播
- 把全局广播改为本地广播
- 注册广播时将exported属性设置为false,表示该广播接收者不对外;
- 在广播发送和接收时,增设相应权限permission,用于权限验证;
- 发送广播时通过intent.setPackage(packageName)指定该广播接收器所在的包名,因此保证该发送出去的广播只会发送到指定包名的App内的广播接收者。
- 使用LocalBroadcastManager类
1 | //注册应用内广播接收器 |
粘性广播
Android5.0之后已经废弃,不推荐使用
App1能否接收到App2的广播?
能,只要使用全局的BroadCastRecevier能进行跨进程通信,不过只能被动接收广播。 多说一句,当然不能用LocalBroadCastRecevier,这个只限于本进程内部的广播。