Broadcast
- 普通广播:同时收到广播,消息的传递效率比较高;
Context.sendBroadcast()
- 有序广播:广播具有优先级,优先级大的先接收到广播;
Context.sendOrderedBroadcast()
- 粘性广播:如果发送者发送了某个广播,而接收者在这个广播发送后才注册自己的Receiver,这时接收者便无法接收到刚才的广播,为此Android引入了StickyBroadcast,在广播发送结束后会保存刚刚发送的广播(Intent),这样当接收者注册完Receiver后就可以继续使用刚才的广播。如果在接收者注册完成前发送了多条相同Action的粘性广播,注册完成后只会收到一条该Action的广播,并且消息内容是最后一次广播内容。系统网络状态的改变发送的广播就是粘性广播。
Context.sendStickyBroadcast(Intent) // 需要增加权限 <uses-permission android:name="android.permission.BROADCAST_STICKY"/>
注册方式
1、静态注册
2、动态注册
存在以下的一些区别:
- 资源消耗不同。registerReceiver可以手动控制,所以适当的注册和取消注册能节省系统资源,receiver标签系统开机后一直有效。
- 有效期不同。通过registerReceiver注册的BroadcastReceiver在对其进行注册的Context对象"销毁"了或者调用了unregisterReceiver方法时也就失效了,而通过receiver标签注册的BroadcastReceiver只要应用程序没有被删除就一直有效。
- 对registerReceiver函数的调用许可不同。通过registerReceiver注册的BroadcastReceiver在其onReceive函数中可以再次调用某个Context的registerReceiver函数,而通过receiver标签注册的BroadcastReceiver不允许再调用某个Context的registerReceiver函数。
- 使用情况不同。对于自己发送和接受的广播可以通过registerReceiver注册,对于系统常用广播的接收通常用receiver标签注册。
广播的安全性
BroadcastReceiver的设计初衷就是从全局考虑的,可以方便应用程序和系统、应用程序之间、应用程序内的通信,所以对单个应用程序而言BroadcastReceiver是存在安全性问题的。
这样的安全性问题,可以按照下面的方案解决:
- 注册广播时,增加权限permission;这样只有拥有这个权限的应用发出的广播才会被接收。需要在应用中声明使用该权限:
注册方式:<users-permission android:name = "com.android.permission.SEND.XXX"/>
// 动态设置
registerReceiver(BroadcastReceiver, IntentFilter, permission, android.os.Handler)
// 静态,这里可以再增加android:exported="false"属性表示接收者对外部应用程序不可用,即不接受来自外部的广播。
<receiver android:name=".XXXReceiver"
android:permission="com.android.permission.SEND_XXX">
<intent-filter>
<action android:name="com.android.XXX_ACTION" />
</intent-filter>
</receiver>
- 发送广播时,增加权限permission;使得只有具有permission权限的Receiver才能接收此广播要接收该广播。
在接收广播的应用中注册权限:sendBroadcast("com.andoird.XXX_ACTION", "com.android.permission.RECV_XXX");
<users-permission android:name = "com.android.permission.RECV.XXX"/>
- LocalBroadcastManager解决
注册registerReceiver过程
registerReceiver最后返回的是Sticky的Intent对象,所以需要注意下粘性广播。
发送sendBroadcast过程
LocalBroadcastManager
使用LocalBroadcastManager有如下好处:
- 发送的广播只会在自己App内传播,不会泄露给其他App,确保隐私数据不会泄露
- 其他App也无法向你的App发送该广播,不用担心其他App会来搞破坏
- 比系统全局广播更加高效
LocalBroadcastManager的高效体现在,它的实现完全是本地的,没有涉及到Binder的东西,核心是Handler,匹配IntentFilter实现的。LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this)
总结
1.广播接收者的生命周期是非常短暂的(10s),在接收到广播的时候创建,onReceive()方法结束之后销毁
2.广播接收者中不要做一些耗时的工作,否则会弹出Application No Response错误对话框
3.最好也不要在广播接收者中创建子线程做耗时的工作,因为广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉
4.耗时的较长的工作最好放在Service中完成