[TOC]

概述

​ BroadcastReceiver(广播接收器)是Android四大组件之一,顾名思义,通过广播的方式进行消息传递,其本质是一个全局的监听器,可以监听到各种广播,可以用来实现不同组件之间的通信。广播最大的特点就是发送方并不关心接收方是否接到数据,也不关心接收方是如何处理数据的,通过这样的形式来达到接、收双方的完全解耦合。

广播的类型

​ 根据不同的角度,广播可以分为不同的类型,这些分类基本都是根据广播发送者来决定的。下面咱们来详细探讨一下这些类型。

1、自定义广播和系统广播

​ 根据发送的广播是用户自己定义的还是由系统定义的,可将广播分为自定义广播和系统广播。这个比较简单,容易理解。

​ Android系统中内置了多个系统广播,只要涉及到手机的基本操作,基本上都会发出相应的系统广播。如:开启启动、电量变化、网络状态改变,拍照,屏幕关闭与开启,点亮不足等等。每个系统广播都具有特定的intent-filter,其中主要包括具体的action,系统广播发出后,将被相应的BroadcastReceiver接收。系统广播在系统内部当特定事件发生时,有系统自动发出。

2、普通广播和有序广播

根据广播发送者发送的是否为有序广播,可以将广播分为普通广播(无序广播)和有序广播。

(1)普通广播

​ 普通广播,有的文章中称为标准广播,又称无序广播,这种广播完全是异步的,以异步的方式发送广播给接收者。Android系统AMS(ActivityManagerService)发出广播后,所有满足条件的广播几乎可以同时受到广播,没有顺序之分,也无需向AMS返回处理结果。这种方式下,各个接收者之间不会相互干扰,几乎同一时刻收到通知,效率较高。当然你也可以选择响应或者不响应该事件。

​ 这种广播站通过Context.sendBroadcast()方法发送。但缺点是接收器不能将处理结果传递给下一个接收器,并且无法在中途终止广播。

1
2
3
4
5
Intent intent = new Intent();
//对应BroadcastReceiver中intentFilter的action
intent.setAction("test");
//发送广播
sendBroadcast(intent);

(2)有序广播

​ 这是一种同步执行的广播,通过Context.sendOrderedBroadcast()方法发送,这种广播发出后,通过receiver的intent-filter中的android:priority属性来设置优先级,优先级从-1000~1000,数越大,优先级越高,使用setResult()方法把结果传递给下一个接收者,通过getResult()方法获取上一个接收者传递过来的结果,并可以通过abortBroadcast()方法丢弃该广播,使该广播不再传递给下一个接收者。

3、粘性广播

​ 粘性广播通过Context.sendStickBroadcast()方法来发送,用此方法发送的广播会一直滞留,当有匹配此广播的接收器被注册后,该广播接收器就会收到此广播。使用此广播时,需要获得BROADCAST_STICKY权限。(在 android 5.0/api 21后不再推荐使用)

1
<uses-permission android:name="android.permission.BROADCAST_STICKY" />

4、本地广播

​ 以上广播都属于全局广播,发出去的广播,只要有匹配的接收者,就可以收到广播。这样一来会造成一些问题,一是消耗性能,二是容易引起安全性的问题,为了能够简单的解决这方面的问题,Android引入了一套广播本地广播机制,使用该机制发出的广播只能够在本应用内部进行传递,并且广播接收器也只能接收来自本应用发出的广播。

​ 使用方法:

​ 1.注册本地广播接收器

​ 2.发送本地广播

​ 3.注销本地广播接收器

广播的注册

静态注册

​ 静态注册就是在AndroidManifest中注册BroadcastReceiver,并指定它所接收的广播种类,如下面配置的MyReceiver用来接收开机广播。

​ 注意:从Android8.0开始,所有的隐式广播都不允许使用静态注册的方式进行接受,所以建议大家不要在清单文件中进行静态注册广播接收者。

1
2
3
4
5
6
7
8
9
10
11
12
 public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

}
}

<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

​ 在 Android 8.0 之前,这样就可以了,但是我们前面已经说过,在 Android 8.0 系统之后,静态注册的 BroadcastReceiver 是无法接收隐式广播的,而默认情况下我们发出的自定义广播恰恰都是隐式广播。

所以我们需要调用 IntentsetPackage() 方法,并传入当前应用程序的包名。使得这条广播变成显示广播或者通过 Intent.setComponent(包名, 接收广播类的完整类名)来显示的设置广播接收者。

动态注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

}
}


Override
protected void onResume() {
super.onResume();
mReceiver = new MyReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("test");
registerReceiver(mReceiver, intentFilter); // 注册广播接收器
}

@Override
protected void onPause() {
unregisterReceiver(mReceiver); // 注销广播接收器
super.onPause();
}

广播应用场景

  1. 不同组件间的通信(含: 应用内和不同应用之间)
  2. 多线程通信
  3. 组件和系统之间的通信(比如网路变化)