Broadcast(广播)是一种广泛应用在应用程序之间传输信息的机制。Android提供了一套完整的API,允许应用程序自由地发送和接收广播,发送广播使用大家都熟悉的Intent,而接收广播并进行响应的任务则交给了BroadcastReceiver(广播接收器)。
今天,我们就来聊聊BroadcastReceiver。
本文的要点如下:
- 简介
- 分类
- 使用方法
- 自定义BroadcastReceiver
- 注册
- 发送广播
简介
BroadcastReceiver是一个全局的监听器,属于Android四大组件之一。主要用于监听 / 接收应用 App 发出的广播消息,并做出响应。
分类
Android系统中的广播主要可以分为四种类型:
- 普通广播(Normal Broadcast)
- 系统广播(System Broadcast)
- 有序广播(Ordered Broadcast)
- 本地广播(Local Broadcast)
本来还有一种粘性广播,不过由于在Android5.0 & API 21中已经失效,所以在这里也就不提了。
使用方法
一、自定义接收器类并继承BroadcastReceiver,必须复写抽象方法onReceive()方法。
class ForceOfflineReceiver extends BroadcastReceiver{
//收到广播后弹出窗口
@Override
public void onReceive(final Context context, Intent intent) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Warning")
.setCancelable(false)//不可取消
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
ActivityCollector.finishAll();
Intent intent = new Intent(context, LoginActivity.class);
startActivity(intent);
}
}).show();
}
}
广播接收器接收到相应广播后,会自动回调 onReceive() 方法。默认情况下,由于广播接收器运行在 UI 线程,因此,onReceive()方法不能执行耗时操作,否则将导致ANR。
一般情况下,onReceive方法会涉及与其他组件之间的交互,如发送Notification、启动Service等。
二、注册BoardcastReceiver
注册的方式分为两种:在AndroidManifest.xml里静态注册、在代码中动态注册。
静态注册:
在AndroidManifest.xml里通过
标签声明
//用于接收网络状态改变时发出的广播
动态注册:
在代码中调用Context.registerReceiver()方法。
//实例化IntentFilter
IntentFilter intentFilter = new IntentFilter();
//设置接收广播的类型
intentFilter.addAction("com.bupt.testlogin.FORCE_OFFLINE");
//实例化BroadcastReceiver子类ForceOfflineReceiver类
ForceOfflineReceiver forceOfflineReceiver = new ForceOfflineReceiver();
//动态注册
registerReceiver(forceOfflineReceiver,intentFilter);
有注册就要有注销,动态注册后记得要销毁广播,否则会产生内存泄露。
@Override
protected void onPause() {
super.onPause();
if(forceOfflineReceiver != null){
unregisterReceiver(forceOfflineReceiver);//销毁广播
forceOfflineReceiver = null;
}
}
动态广播最好在Activity的onResume()注册、onPause()注销,理由如下:
- 因为onPause()在App死亡前一定会被执行,就能保证广播在App死亡前一定会被注销,从而防止内存泄露。
不在onCreate() & onDestory() 或 onStart() & onStop()注册、注销是因为:
- 当系统因为内存不足(优先级更高的应用需要内存时)要回收Activity占用的资源时,Activity在执行完onPause()方法后就会被销毁,有些时候onStop(),onDestory()不会被执行。当再回到此Activity时,会从onCreate方法开始执行。
动态注册和静态注册的区别:
其实两种方式都是完成了对接收器以及它能接收的广播值这两个值的定义。这两种注册方法区别是:动态注册的接收器必须要在程序启动之后才能接收到广播,而静态注册的接收器即便程序未启动也能接收到广播,比如想接收到手机开机完成后系统发出的广播就只能用静态注册了。
三、发送广播
发送广播时用Intent来实现的,本质上就是广播发送者将此广播的“意图(Intent)”通过sendBroadcast()方法发送出去。另外,可以在Intent中携带参数,从而实现信息的传递。当然,不同类型的广播发送方式会有些许的不同,具体如下:
1.普通广播
最常用的广播就是普通广播了,用法也非常简单:
Intent intent = new Intent();
//对应BroadcastReceiver中intentFilter的action
intent.setAction(BROADCAST_ACTION);
//发送广播
sendBroadcast(intent);
若被注册了的广播接收者中注册时intentFilter的action与上述匹配,则会接收此广播(即进行回调onReceive())。
普通广播是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们接收的先后是随机的。另外,接收器也无法截断普通广播。
2. 系统广播
Android系统中内置了多个系统广播:许多涉及到手机的基本操作(如开机、网络状态变化、拍照等等),系统都会自动发出相应的广播,在APP内只需要注册广播接收器即可。
每个广播都有特定的Intent - Filter(包括具体的action),Android系统广播action如下:
系统操作 | action |
---|---|
监听网络变化 | 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 |
3. 有序广播
有序广播是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递,所以此时的广播接收器是有先后顺序的,且优先级(priority)高的广播接收器会先收到广播消息,Priority属性相同者,动态注册的广播优先。有序广播可以被接收器截断使得后面的接收器无法收到它,也可以被接收器修改,之后的接收器会接收到修改后的广播。
使用方法与普通广播的差异仅在于发送广播调用的方法:
Intent intent = new Intent();
//对应BroadcastReceiver中intentFilter的action
intent.setAction(BROADCAST_ACTION);
//发送有序广播
sendOrderedBroadcast(intent);
4. 本地广播
无论是普通广播、有序广播还是系统广播,都属于全局广播,即发出的广播可被其他应用程序接收到,且我们也可接收到其他任何应用程序发送的广播。这会带来一些应用间的冲突以及安全性问题。因此,Android系统提供了一套本地广播机制。
本地广播可理解为一种局部广播,广播的发送者和接收者都同属于一个APP。
实现本地广播的发送和接收也很简单,主要使用了一个LocalBroadcastManager来对广播进行管理,并提供了相应的发送广播和注册广播接收器的方法,具体的使用方法如下
//获取LocalBroadcastManager实例
LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.bupt.testlogin.FORCE_OFFLINE");
forceOfflineReceiver = new ForceOfflineReceiver();
//动态注册
localBroadcastManager.registerReceiver(forceOfflineReceiver,intentFilter);
//注销
localBroadcastManager.unregisterReceiver(forceOfflineReceiver);
//发送本地广播
localBroadcastManager.sendBroadcast(intent);