四大组件之Broadcast Receiver

更新时间 修改意见
2016-08-02 陈敏

第1节 Broadcast Receiver概述

很多时候,我们希望一个应用程序在它没有运行起来的时候,也能感知系统状态的某些变化,如果条件合适,就让这个应用运行起来。

比如,一个拦截骚扰电话的应用,平时它可能并不需要运行起来,它只关心有电话来的时候,看看这个号码是不是骚扰电话的号码,如果是就给用户发出一个提示,如果不是,那就和它没有关系,啥也不做。

为了实现这类功能,安卓系统引入了四大组件之一的BroadcastReceiver,设计了一套广播与接收的机制,

  1. 任何应用或者安卓系统的自身组件可以像发送无线电波一样,向系统发出一条广播信息Broadcast
  2. 信息在系统中按照一定的规则传播(传播的规则稍后会详细介绍);
  3. 任何应用或者安卓系统的自身组件都可拥有一台接收机Broadcast Receiver,这台接收机会告诉安卓系统,它能接收某种特定的广播;
  4. 如果安卓系统辨别出当前系统中传播的广播,正是某台接收机关注的广播,那么它就会把接收机运行起来,让接收机决定下一步怎么做:是运行别的组件(Service或者Activity)继续进一步的响应,或者是忽略这条广播。

第2节 自定义Broadcast Receiver

无论是应用还是系统组件,它们定义Broadcast Receiver的方式都是一样。

定义Broadcast Receiver有两种方式,

  1. 静态定义:将Broadcast Receiver声明到AndroidManifest.xml配置文件当中,它的特点是应用不必运行起来,系统能通过配置文件的描述判断当前系统中的广播是否是这台接收机关注的;

  2. 动态定义:在代码中动态生成Broadcast Receiver,它的特点是应用要运行起来,在运行的过程当中判断当前系统中的广播是否是这台接收机关注的;

2.1 静态Broadcast Receiver

首先来看看如何定义一个静态的Broadcast Receiver

  1. 继承BroadcastReceiver类,实现它的onReceive接口,

  2. AndroidManifest.xml配置文件当中,声明创建的Broadcast Receiver

    这里intent-filter标签中的action android:name属性设置的值custom.action.mybroadcast,就是这台接收机关注的广播。

当名称为custom.action.mybroadcast的广播在系统中传播的时候,MyReceiver就会被运行起来,并触发它的onReceive()函数。开发者就需要在这里添加对应逻辑处理。

2.2 动态Broadcast Receiver

当应用运行起来以后,即使AndroidManifest.xml文件中没有声明过Broadcast Receiver也没有关系,它可以被动态的创建,

  1. 和创建静态Broadcast Receiver类似,首先要继承BroadcastReceiver类,实现它的onReceive接口,

  2. 注册Broadcast Receiver,并告诉系统这个Broadcast Receiver关注哪些广播,可以添加多种关心的广播,

  3. 使用完毕后,一定要注销Broadcast Receiver,否则系统会给出警告提示。

动态的Broadcast Receiver在注册使用完成之后一定要注销,不然会占用系统资源、浪费资源。

第3节 发送Broadcast

任何应用或者安卓系统的自身组件可以向系统发出广播信息Broadcast,只要使用ContextsendBroadcast()方法就可以了,

发送出去的广播可以分成两类,一类是无序广播,一类是有序广播。

3.1 无序广播

这是一种不需要考虑接收者接收顺序的广播,比如说有3个接收机,都关注custom.action.mybroadcast这种广播,无所谓谁先收到谁后收到。接收机不能阻止其它接收机获取到这条广播。

3.1.1 发送

发送无序广播,只要使用ContextsendBroadcast()方法就可以了,

3.1.2 接收

AndroidManifest.xml中声明静态Broadcast Receiver的时候,

就像前面介绍的那样,不用做什么特别的处理。

3.2 有序广播

这是一种需要考虑接收者接收顺序的广播,比如说有3个接收机,都关注custom.action.mybroadcast这种广播,那么安卓系统将根据这3个接收机声明的优先级进行广播的投递。

而且有序广播是可以被阻截的。

比如,一个广播按照顺序传递给3个接收机-A B C,但是B将广播拦截了,因此C将不会收到这个广播。

3.2.1 发送

3.2.1 接收

接收的时候,需要给intent-filter标签设置android:priority属性,表示这个接收机的优先级。优先级从-1000到1000,数值越大,优先级越高。

接收到广播以后,Broadcast Receiver可以将广播拦截,禁止它往下传播,

如果接收机1onReceive()中,希望把数据传递给下个接收机2

  1. 接收机1可以使用setResultExtras()方法,

  2. 接收机2中,

假如希望将数据放到onReceive()传入的Intent当中,是不会传递成功的,

传递数据,一定要通过BroadcastReceiver提供的setResultExtras()方法。

第4节 Broadcast的使用权限

为广播设置权限要考虑两方面的问题。

  1. 作为广播的发送者,希望限制广播的接收者,只让特定的应用组件接收到发出的广播;
  2. 作为广播的接收者,不希望任何组件都能模仿它关心的广播,因此希望在接受广播的时候能检查一下这条广播的发送者是否具有发送这条广播的资格;

无论是上面哪种情况,解决方法都是一样的:为发送者和接收者都设置一个相同的权限,只有它们的权限匹配上了,广播机制才能产生效果。

4.1 限制接收者

假设组件A要发布广播,

  1. AndroidManifest.xml文件中,与同级的位置,对外声明使用权限,表示这个应用发布了一个叫做com.anddle.receiver.receivebroadcast的权限,

  2. 在组件向整个系统发布广播的时候,就采用,

    这里的广播权限com.anddle.receiver.receivebroadcast,就是AndroidManifest.xml中声明的权限。

接收者要接收这种广播的时候,

  1. 接受者需要在它的AndroidManifest.xml当中静态的定义好接收机对应的receiver,或者在代码当中动态的定义好接收机对应的receiver

  2. 在它的AndroidManifest.xml当中,声明要使用的权限,

4.2 限制发送者

假设接收者1要设置权限,只接收特定发送者发来的广播,

  1. AndroidManifest.xml文件中,对要设置权限的Broadcast Receiver设置上android:permission属性,该属性值可以任意指定一个字符串。通常使用程序的包名作为其中的一部分,这样可以避免和其他应用中的权限声明冲突。例如com.anddle.receiver.sendbroadcast

  2. AndroidManifest.xml文件中,与同级的位置,对外声明前面使用的标签,表示这个应用发布了一个叫做com.anddle.receiveraccess的权限,

    其中android:name属性的值,就是标签中设置的android:permission的值。

发送者B要发送相应的广播,就要

  1. 在B的AndroidManifest.xml中加入权限的使用,

    其中,标签中设置的android:name的值,就是应用A中对外声明的那个Broadcast Receiver的权限值。

  2. 使用代码发送广播,

4.3 接收其它应用的广播

在应用的AndroidManifest.xml文件中,Broadcast Receiver具有android:exported属性,

  1. android:exported属性设置成true:可以接收其他应用发来的广播;
  2. android:exported属性设置成false:不能接收其他应用发来的广播;

所以当两个不同的应用之间需要发送和接收广播的时候,需要把这个属性设置成true

第5节 系统的广播

系统提供了很多现成的广播,开发者可以根据自己应用的需要,关注某些特定的广播。这里介绍几种使用频率最高的广播。

5.1 开机完成

有的时候,应用希望在开机完成之后,启动一个在后台运行的Service。例如我们常用的微信应用,开机后会启动一个Service和网络相连,如果有消息来,就通知我们有朋友发消息来了。

但是系统刚启动,用户没有主动打开微信,那么这个微信的Service是不会运行起来的。这时候,就可以使用Broadcast Receiver了,让它关注一个叫做android.intent.action.BOOT_COMPLETED的广播,

这样,等开机完成后,系统发出android.intent.action.BOOT_COMPLETED广播后,MyReceiver就可以收到这条广播,进行自己的处理-例如运行一个Service了。

使用这条广播有个很重要的地方需要注意,从Android 4.0的系统开始,安装了这个应用以后,用户必须手动启动一次该应用(运行该应用的Activity),这样重启设备之后,就能收到android.intent.action.BOOT_COMPLETED广播了。

5.2 时间变化

如果我们很关心时间的变化,例如要实现一个时钟,每一秒的变化,时间设置改变,时区变化都将是关心的内容。

所以,可以创建动态的接收机监听3种广播,

  1. Intent.ACTION_TIME_TICK
  2. Intent.ACTION_TIME_CHANGED
  3. Intent.ACTION_TIMEZONE_CHANGED

同时将接收机定义成,


/**************************************************************************/
* 版权声明
* 本教程只在CSDN安豆网发布,其他网站出现本教程均属侵权。
/
**************************************************************************/