天天看点

Android App开发基础篇—四大组件之Broadcast

作者:书生听雨景阑珊林

Android 四大组件—组件间的通信方式Broadcast(广播)

前言:假设有这样一个场景:在程序中要将一条消息同时发送给多个接收者,比如应用中启动的多个Activity,或者系统中的其他多个应用,但是并不必关心接收者是否接收到或者如何处理,该如何实现呢?想想现实中,当我们遇到类似的情况的时候,最好的方法是什么?相信大家很容易就能想到了。没错,就是广播。在Android中,同样也提供了广播机制来实现这种功能。

一、概念

Android中的广播与传统意义上的电台广播类似,具有单向、群发,且不关注结果的特点。就是说,一个广播发送者负责将广播发送给任意个广播接收者,并且发送者并不关心接收者是否接收到广播或如何处理。这是一种典型的发布—订阅模式,即观察者模式。通过这种模式,实现了发送方和接收方的完全解耦,增加了系统的集成和扩展性。

二、适用场景分析

Broadcast作为Android中组件间的通信方式,其主要适用的场景有:

(1)同一App内部同一组件内的消息通信(单个或多个线程)

(2)同一App内部不同组件间的消息通信(单个进程)

(3)同一App具有多个进程的不同组件间的消息通信

(4)不同App之间的组件间的消息通信

(5)特定情况下系统与App间的消息通信

以上列出的是Broadcast的适用场景,然而并非在每个场景下都要用Broadcast。下面来具体分析:

场景(1):由于该类问题可以通过诸如“扩展变量作用域”、“基于接口的回调”、“Handler—post/Handler—Message”等方式进行处理,因此不推荐使用Broadcast。

场景(2):对于某些比较复杂的情况,有时候基于接口的回调方式可能不太方便解决问题。此时,形如EventBus一类的事件发布/订阅框架将会是很好的解决方案。然而,有些人可能还没有接触过这类框架,那么使用Broadcast也是很好的选择。

场景(3)(4)(5):由于涉及到不同进程间的通信,适时的使用Broadcast应该是非常适宜的方案。

三、Broadcast的使用

Android中的广播分为普通广播、有序广播、本地广播、粘性广播、以及系统广播。下面分别来看一下。

3.1 广播的使用

由于几种类型的广播的使用方式大体上相同,只是在具体的发送方法上有所差异。因此先统一简述一下广播的使用步骤:

(1)广播的3个要素

Android中的广播机制包含3个基本要素,分别是用于发送广播的Broadcast,用于接收广播的BroadcastReceiver,以及用于传递信息的Intent。

(2)广播的发送

要发送一个广播,写法很简单,这里以发送普通广播为例,只需在需要发送广播的地方执行下列代码:

//实例化Intent对象
Intent intent = new Intent();
//设置action,这里的action与IntentFilter的action对应
intent.setAction("test");
//设置要传递的信息
intent.putExtra("broadcast", "test");
//发送广播
sendBroadcast(intent);           

(3)广播的接收

广播的接收,需要弯沉两个步骤。首先需要先创建一个广播接收者BroadcastReceiver,然后还要注册对应的广播。

BroadcastReceiver的创建只需新建一个类,继承BroadcastReceiver类即可。创建好后,会覆写一个onReceive()方法,当接收到广播后,便会回调此方法。代码如下:

package com.test.myapplication;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class MyReceiver extends BroadcastReceiver {
    public MyReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        //接收到广播后会回调此方法
    }

}
           

创建好BroadcastReceiver后,接下来还需要注册。注册的方式有两种:静态注册和动态注册。

● 静态注册:就是在AndroidManifest.xml里面注册广播。这种方式的特点是所注册的广播是基于整个应用的,即无论在app运行的任何时刻,只要系统中有对应的广播发出,且app具有接收权限,那么app都会接收到该广播。注册方式如下:

<receiver  android:name=".MyReceiver"  android:enabled="true"  android:exported="true"  android:permission="test"  android:process="test">  <intent-filter>  <action android:name="android.provider.Telephony.SMS_RECEIVED" />  </intent-filter> </receiver>           

上面的代码在AndroidManifest.xml里面对新建的BroadcastReceiver进行了注册,其中设置了接收的广播类型为系统的短信消息:

name属性,就是新建的BroadcastReceiver的"包名.类名",

exported属性,其作用是决定此BroadcastReceiver能否接收其他App所发出的广播。其值由有无intent-filter来决定。当有intent-filter的时候,其值默认为true,如果没有则默认为false。当然也可以手动修改。

permission属性,当设置时,只有拥有对应权限的app所发送的广播才会被接收到,其他广播则不会被接收。

progress属性:设置BroadcastReceiver所在的进程,默认为App进程。

<intent-filter>:指定此BroadcastReceiver所接收的广播类型。其中的action与发送广播是所设置的setAction()方法的参数对应。

● 动态注册:动态注册就是在代码中通过registerReceiver()方法进行注册。只需在需要注册的地方执行下列代码:

//实例化IntentFilter对象
IntentFilter intentFilter = new IntentFilter();
//设置接收广播的类型。与发送广播时的setAction()方法对应
intentFilter.addAction("test");
//注册BroadcastReceiver
registerReceiver(mReceiver, intentFilter);           

然后在无需接收广播的时候,要记得使用unregisterReceiver()取消注册。例如在Activity关闭的时候,在onDestory()里面:

@Override
protected void onDestroy() {
    super.onDestroy();
    unregisterReceiver(mReceiver);
}           

注意:Android中凡是涉及register的,必须在适当的时机进行unregister。

3.2 几种类型的广播介绍

(1)普通广播

普通广播通过Context.sendBroadcast()方法来发送,消息传递效率比较高,但所有接收方接收消息的顺序是无需的,即无法确定哪个接收方会先收到广播消息。普通广播一旦发送便无法终止,直到没有与之匹配的广播接收器为止。

另外,由于Android 4.2中加入了多用户特性,因此演变出了sendBroadcastAsUser()方法来区分不同的用户。

(2)有序广播

有序广播通过Context.sendOrderedBroadcast()方法来发送。有序广播具有以下特性:

● 所有的广播接收器会依照优先级依次接收广播消息。广播接收器的优先级通过intent-filter的priority属性来设置,数值越大优先级越高。如果优先级相同,则动态注册的接收器会先于静态注册的接收器先接收到广播。

● 当某个广播接收器接收到广播后,可以通过setResult()方法来修改广播的内容,然后在下个广播接收器中使用getResultData()、getResultExtras()方法来接收修改后的结果,或者使用intent.getXXX()方法来接收广播的原始消息。在广播传播的过程中,还可以使用abortBroadcast()方法来终止广播的发送,使广播不再继续向下传播。

(3)粘性广播

粘性广播通过Context.sendStickyBroadcast()方法来发送,不过该方法在android .50(api 21)中已经被deprecated,所以并不推荐使用。粘性广播一旦发送,便会一直滞留,当有匹配的广播接收器注册时,此接收器便会接收到此广播。可以使用removeStickyBroadcast()方法来移除。使用粘性广播需要获得BROADCAST_STICKY权限:

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

(4)系统广播

Android系统中内置了多种系统广播,基本上涉及到手机的基本操作都会发出相应的系统广播,如:手机网络状态变化、手机SMS短信、开机启动等。系统广播在系统内部特定事件发生时由系统发出,然后由对应的广播接收器接收。

(5)本地广播

上述广播都是系统全局的广播,在系统内的所有应用程序都有可能接收到,如此便会产生安全隐患。为此,Android在Support V4包增加了本地广播,使广播能够仅限于在当前App应用中发送和接收。本地广播的发送使用LocalBroadcastManager,即将发送普通广播时使用的sendBroadcast、registerReceive、unregisterReceiver替换为LocalBroadcastManager.getInstance(Context context)中对应的方法。具体如下:

函 数 作 用

LocalBroadcastManager.getInstance(context).

registerReceiver(receiver,intentFilter)

注册Receiver

LocalBroadcastManager.getInstance(context).

unregisterReceiver(receiver)

注销Receiver

LocalBroadcastManager.getInstance(context).

sendBroadcast(intent)

发送异步广播

LocalBroadcastManager.getInstance(context).

sendBroadcastSync(intent)

发送同步广播

后记:Broadcast作为Android四大组件之一,其主要作用是用于组件间的通信。Android中的Broadcast采用了典型发布—订阅型的观察者模式,其发送方与接收方是完全解耦的。发送方仅负责发送广播消息,而不关心接收方是否能够接收到,或者如何如理消息。Broadcast共有五种类型,分别为普通广播、有序广播、粘性广播、系统广播、本地广播。

继续阅读