特点:是一个典型的发布-订阅模式,发送方不关心接收方是否接到数据,也不关系接收方如何处理数据
广播指定相应的action等信息,每个接收器根据intentFilter过滤出自己要接收的广播
注意:
- 安卓7以上系统,在清单中声明接收器通常不起作用
- 当BroadcastReceiver在onReceive()运行时会被视为前台进程。结束onReceive()时BroadcastReceiver将不再是活跃状态,会被设为低优先级进程非常容易被杀掉。通常不要对广播接收器进行耗时操作,如果非要进行耗时操作,那么可以开启子线程。
广播分类
普通广播
优点:消息传递效率高
缺点:
- 执行顺序不确定
- 接受者无法将处理的结果传递给下一个接受者
- 无法中断传播,直到没有与之匹配的广播接收器为止
发送广播:
sendBroadcast(new Intent("hello"));
有序广播
优点:
- 所有广播接收器按优先级顺序执行,通过intent-filer的android:priority属性
- 当前广播接收器可使用setResult()函数将结果传递给下一个广播接收器,通过getResult()函数获取上一个广播接收器返回的结果
- 可以调用abortBroadcast()函数丢弃该广播,使其不再传送给其他广播接收器
显然有序广播优化了普通广播的缺点
设置广播优先级
mHelloBroadcastReceiver = new HelloBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter("hello");
intentFilter.setPriority(50);
registerReceiver(mHelloBroadcastReceiver,intentFilter);
发送广播
sendOrderedBroadcast(new Intent("hello"),null);
本地广播
上述的广播都是全局的,如果不需要向应用程序外部的组件发起广播,可以使用本地广播,提高效率。
LocalBroadcastManager可以实现限于应用内的广播
//注册广播
LocalBroadcastManager.getInstance(this).registerReceiver(@NonNull BroadcastReceiver receiver,
@NonNull IntentFilter filter)
//注销广播
LocalBroadcastManager.getInstance(this).unregisterReceiver(@NonNull BroadcastReceiver receiver)
//发送异步广播
LocalBroadcastManager.getInstance(this).sendBroadcast(@NonNull Intent intent)
//发送本地广播
LocalBroadcastManager.getInstance(this).sendBroadcastSync(@NonNull Intent intent)
sticky广播
通过Context.sendStickyBroadcast(Intent intent)发送。发送粘性广播还需要BROADCAST_STICKY权限:
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
特点:
- 此广播会滞留,即使已经有广播接收器处理了该广播,此广播认可继续被接受。直到调用removeStickyBroadcast()函数
BroadcastReceiver
当接受到广播时,会调用onReceive()方法。
public class HelloBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = HelloBroadcastReceiver.class.getSimpleName();
@Override
public void onReceive(Context context, Intent intent) {
Log.e(TAG,"hello");
}
}
BroadcastReceiver注册方式
静态注册
<receiver
android:name=".components.broadcast.HelloBroadcastReceiver"
android:exported="false">
<!--intent过滤器指定接收者订阅的广播操作。-->
<intent-filter>
<action android:name="hello"/>
</intent-filter>
</receiver>
exported为false表示接收方不接受来自应用外的广播
注意:
当应用程序关闭后如果有信息广播来,程序也会被系统调用,自己运行。
静态注册的接收器必须是独立外部类或者静态内部类,因为非静态内部类依赖外部类的实例
动态注册
registerReceiver(new HelloBroadcastReceiver(),new IntentFilter("hello"));
当用来注册的 Activity 关掉后,广播也就失效了。
取消注册
unregisterReceiver(android.content.BroadcastReceiver)
这里的注册和取消注册是针对非本地广播的。
本地广播和非本地广播区别
BroadcastReceiver,用于应用之间的传递消息,通过binder实现
LocalBroadcastReceiver ,用于应用内部传递消息,通过handler实现
扩展
安全问题
广播会有如下隐患:
别的程序监听我们的广播,造成数据泄露
别的程序冒充我们的程序发送广播
频繁发送广播,启动广播接收器,甚至崩溃
解决办法:
指定应用自己的权限,拥有该权限的应用才能接受广播
发送方发送广播时指定权限,接收方注册接收器时说明权限
详情见自定义权限
数据限制
Intent在传递数据时是有大小限制的,大约限制在1MB之内
你用Intent传递数据,实际上走的是跨进程通信(IPC),跨进程通信需要把数据从内核copy到进程中,每一个进程有一个接收内核数据的缓冲区,默认是1M;如果一次传递的数据超过限制,就会出现异常。
实际运用
常用于接受系统广播,例如:进程拉活
广播,eventbus,handler的区别
https://blog.csdn.net/sdsxtianshi/article/details/80598165
待学习,盲点
注意
安卓7以上系统,在清单中声明接收器通常不起作用
BroadcastReceiver在onReceive()运行时会被视为前台进程。
BroadCastReceiver发生ANR的时间是10秒