Android之BroadcastReceiver基础学习
[TOC]
概述
BroadcastReceiver(广播接收器)是Android四大组件之一,顾名思义,通过广播的方式进行消息传递,其本质是一个全局的监听器,可以监听到各种广播,可以用来实现不同组件之间的通信。广播最大的特点就是发送方并不关心接收方是否接到数据,也不关心接收方是如何处理数据的,通过这样的形式来达到接、收双方的完全解耦合。
广播的类型
根据不同的角度,广播可以分为不同的类型,这些分类基本都是根据广播发送者来决定的。下面咱们来详细探讨一下这些类型。
1、自定义广播和系统广播
根据发送的广播是用户自己定义的还是由系统定义的,可将广播分为自定义广播和系统广播。这个比较简单,容易理解。
Android系统中内置了多个系统广播,只要涉及到手机的基本操作,基本上都会发出相应的系统广播。如:开启启动、电量变化、网络状态改变,拍照,屏幕关闭与开启,点亮不足等等。每个系统广播都具有特定的intent-filter,其中主要包括具体的action,系统广播发出后,将被相应的BroadcastReceiver接收。系统广播在系统内部当特定事件发生时,有系统自动发出。
2、普通广播和有序广播
根据广播发送者发送的是否为有序广播,可以将广播分为普通广播(无序广播)和有序广播。
(1)普通广播
普通广播,有的文章中称为标准广播,又称无序广播,这种广播完全是异步的,以异步的方式发送广播给接收者。Android系统AMS(ActivityManagerService)发出广播后,所有满足条件的广播几乎可以同时受到广播,没有顺序之分,也无需向AMS返回处理结果。这种方式下,各个接收者之间不会相互干扰,几乎同一时刻收到通知,效率较高。当然你也可以选择响应或者不响应该事件。
这种广播站通过Context.sendBroadcast()方法发送。但缺点是接收器不能将处理结果传递给下一个接收器,并且无法在中途终止广播。
1 | Intent intent = new 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 | public class MyReceiver extends BroadcastReceiver { |
在 Android
8.0 之前,这样就可以了,但是我们前面已经说过,在 Android
8.0 系统之后,静态注册的 BroadcastReceiver
是无法接收隐式广播的,而默认情况下我们发出的自定义广播恰恰都是隐式广播。
所以我们需要调用 Intent
的 setPackage()
方法,并传入当前应用程序的包名。使得这条广播变成显示广播或者通过 Intent.setComponent(包名, 接收广播类的完整类名)
来显示的设置广播接收者。
动态注册
1 | public class MyReceiver extends BroadcastReceiver { |
广播应用场景
- 不同组件间的通信(含: 应用内和不同应用之间)
- 多线程通信
- 组件和系统之间的通信(比如网路变化)