一、什么是BroadcastReceiver?
BroadcastReceiver(广播接收器)属于Android四大组件之一,是一个全局监听器,用于监听/接收App发出的广播消息,并作出响应,也用于不同组件之间的相互通信。
二、实现原理
Android的广播使用了设计模式中的观察者模式:基于消息的发布/订阅事件模型。
模型中有3个角色。
1、消息订阅者(广播接收者)
2、消息发布者(广播发送者)
3、消息中心(AMS,即 Activity Manager Service)
示意图如下:
三、使用流程
3.1、自定义广播接收者,继承自BroadcastReceiver基类,必须复写其中onReceive()方法。
广播接收器接收到广播之后,会调用onReceive()方法,一般情况下,onReceive()方法会涉及与其他组件的交互。
public class MyReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Toast.makeText(context,"......onReceive.........",Toast.LENGTH_LONG).show(); Log.i("TAG","......FirstReceive......."); } }
3.2、注册广播
1、静态注册(Android8.0后不推荐使用):
在manifest.xml中注册,示例代码:
<receiver android:name=".SecondReceiver"> <intent-filter> <action android:name="com.example.pc.staticregisterbroadcastreceiver.SecondReceiver"/> </intent-filter>
注意:Android 8.0之后系统不提倡静态注册的广播,会发生广播接收不到的情况,所以最稳妥的方法还是用动态注册。但如果你无法修改代码,也可以通过添加一行代码,来继续使用静态注册。
intent=new Intent();
intent.setComponent(new ComponentName("com.example.pc.staticregisterbroadcastreceiver","com.example.pc.staticregisterbroadcastreceiver.SecondReceiver"));
其中的ComponentName()的两个参数,第一个为广播接收者的包名,第二个为广播接收者的路径。
2、动态注册:
1)在Activity中创建一个自定义的BroadcastReceiver对象。
2)创建一个IntentFilter,并设置这个广播接收者的Action。
3)通过registerReceiver()方法注册广播,其中的两个参数,一个为新建的BroadcastReceiver对象,一个是IntentFilter。
receiver=new MyReceiver(); IntentFilter filter=new IntentFilter(); filter.addAction("com.heep.cn"); registerReceiver(receiver,filter);
3、两种注册方法的区别:
3.3、发送广播:
调用Context的sendBroadcast()发送广播。如果是有序广播,则需要调用sendOrderedBroadcast();
特别注意:
动态广播,最好在Activity的onResume()中注册,在onPause()中注销,以防止内存泄漏。在onResume()注册、onPause()注销是因为onPause()在App死亡前一定会被执行,从而保证广播在App死亡前一定会被注销,从而防止内存泄露。
四、广播的类型:
一般分为5中广播类型:
普通广播(Nomal Broadcast)
系统广播(System Broadcast)
有序广播(Orderd Broadcast)
粘性广播(Sticky Broadcast)
App应用内广播(Local Broadcast)
1、普通广播
即开发者自定义Intent的广播。
intent=new Intent(); intent.putExtra("message","这是一条广播"); intent.setAction("com.example.pc.staticregisterbroadcastreceiver.SecondReceiver"); sendBroadcast(intent);
2、系统广播
Android中内置了多个系统广播:只要涉及到手机的基本操作(如开机、网络状态变化、拍照等等),都会发出相应的广播
每个广播都有特定的Intent - Filter(包括具体的action),Android系统广播action如下:
注:当使用系统广播时,只需要在注册广播接收者时定义相关的action即可,并不需要手动发送广播,当系统有相关操作时会自动进行系统广播
3、有序广播
发送出去的广播被广播接收者按照权限的大小顺序接收
1、按照Priority属性值从大-小排序;
2、Priority属性相同者,动态注册的广播优先;
3、接收广播按顺序接收
4、先接收的广播接收者可以对广播进行截断,即后接收的广播接收者不再接收到此广播;
5、先接收的广播接收者可以对广播进行修改,那么后接收的广播接收者将接收到被修改后的广播
receiver=new MyReceiver(); IntentFilter filter=new IntentFilter(); filter.setPriority(150); filter.addAction("com.heep.cn"); registerReceiver(receiver,filter);
Intent intent=new Intent(); intent.setAction("com.heep.cn"); sendOrderedBroadcast(intent,null);
4、App应用内广播
Android中的广播可以跨App直接通信(exported对于有intent-filter情况下默认值为true)
可能出现的问题:
其他App针对性发出与当前App intent-filter相匹配的广播,由此导致当前App不断接收广播并处理;
其他App注册与当前App一致的intent-filter用于接收广播,获取广播具体信息;
即会出现安全性 & 效率性的问题。
解决方法:
将全局广播设置成局部广播
- 注册广播时将exported属性设置为false,使得非本App内部发出的此广播不被接收;
- 在广播发送和接收时,增设相应权限permission,用于权限验证;
- 发送广播时指定该广播接收器所在的包名,此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。
5. 粘性广播(Sticky Broadcast)
由于在Android5.0 & API 21中已经失效,所以不建议使用,在这里也不作过多的总结。
参考:https://www.jianshu.com/p/ca3d87a4cdf3