Android复习之BroadCastReceiver

是什么

BroadCastReceiver是四大组件之一,相当于一个全局的监听器,用于监听系统全局的广播。

怎么样

由于BroadCastReceiver是全局监听器,因此它可以方便的实现系统中不同组件之间的通信。

怎么用

实现步骤分三步

  1. 创建BroadCastReceiver
  2. 创建需要启动BroadCastReceiver的Intent
  3. 调用Context的sendBroadCast或sendOrderBroadCast方法启动指定的receiver

receiver需要继承BroadCastReceiver并实现onReceive方法,当程序发出一个BroadCast的Intent之后所有匹配了改Intent的BroadCastreceover都有可能会被启动

与Activity和Service不同的是BroadCastReceiver生命周期比较短,本质是一个系统级全局的监听器,专门负责监听个程序所发出的BroadCast

实现了BroadCastReceive就要有与只匹配的Intent

两种匹配intent方式

  1. 在代码中动态设置,通过intentFilter设置Action
  2. 在AndroidMainifest中的receiver标签中设置Action

值得注意的是:

  • 执行完onReceiver后实例会被销毁,生命周期短
  • 发送广播后如果没有与之匹配的receiver,程序不会报错,这与Activity和Service不同
  • 不能在onReceiver方法中做耗时操作,10秒内onReceive方法没有执行完成会被认为程序无响应,因此耗时操作应该在Service中开启线程来执行

两种发送广播的方式

  1. sendBroadCast()普通广播
  2. sendOrderBroadCast()有序广播
    有序广播会根据优先级别按顺序执行接收者,优先接到的可通过abortBroadCast来终止广播,也可以通过setResultExtra()来修改接收到的值并传递,下一个广播在通过getResultExtra()来获取。

两种注册方式

  1. 动态注册,广播会跟随程序的生命周期,在Activity或service中注册,但是必须到onDestroy中销毁,不然会报错
  2. 静态注册,常驻型,即使应用关闭,也能够接收广播

代码演示

xml里面两个按钮,一个动态注册,一个静态注册

这里写图片描述

按照前面说的第一步,先创建一个类TestReceiver继承BroadcastReceiver,该类是一个抽象类,需要实现里面的抽象方法onReceive(Context context, Intent intent)

public class TestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String sky = intent.getStringExtra("sky");
        Log.d("TestReceiver", "接收到的值" + sky);


    }
}

这里面的Intent就是接收传过来的值

第二步,创建匹配该broadCastReceiverIntent,首先要给broadCastReceiver设置一个Action,然后再通过给Intent设置Action,如果Intent的ActionbroadCastReceiverAction匹配,也就是一样,则broadCastReceiver将会被系统启动,接收到Intent传过来的消息。首先注册广播,由上面可知注册有动态注册和静态注册,

  1. 动态注册代码
receiver = new TestReceiver();
        registerReceiver(receiver, new IntentFilter(ACTION));

由于动态注册广播会跟随程序的生命周期,所以注册时实例化应该声明为全局变量,以便在onDestroy中注销,否则会报错!

通过registerReceiver方法来动态注册广播,参数1是被注册的广播,参数2是IntentFilter,设置broadCastReceiver的Action,
2. 动态注册代码

<receiver android:name=".TestReceiver">
            <intent-filter>
                <action android:name="com.cd.broadcastreceiver"></action>
            </intent-filter>
        </receiver>

在AndroidMainifest中注册,这是常驻性注册,即使应用被关闭,接收到匹配的Action,广播也能被启动,也是通过Iintent-filter标签来设置Action。

这两种注册方式,根据需求进行选择,选择动态注册,务必记得手动注销

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

第三步,发送广播,注册好了广播,就可以使用了,在按钮的点击事件中添加如下代码

   /**
                 * 匹配Intent,与这个Action相同的接收者都会接收到。
                 */
                Intent intent = new Intent();
                intent.setAction(ACTION);
                intent.putExtra("sky", "I appreciate the man who are goood at Android");
                sendBroadcast(intent);

这里的ACTION与注册广播时的ACTION要一样,否则匹配失败,无法接收

 public static final String ACTION = "com.cd.broadcastreceiver";

这个ACTION字符串可以是任意的,但是为了看起来规范,选择包名的形式。

点击按钮看到如下输出

这里写图片描述

说明广播是接收到了。

这里是一个接收者一个发送者,而且匹配的ACTION一致,如果有多个接收者匹配了同一个发送者的ACTION会不会都收到,或者多个接收者之间有没有相互的影响呢?

在上面的基础上添加另外两个接收者TestReceiver2TestReceiver3,然后我选择静态注册

  <!--<receiver android:name=".TestReceiver"/>-->
        <receiver android:name=".TestReceiver">
            <intent-filter>
                <action android:name="com.cd.broadcastreceiver"></action>
            </intent-filter>
        </receiver>
        <receiver android:name=".TestReceiver2">
            <intent-filter>
                <action android:name="com.cd.broadcastreceiver"></action>
            </intent-filter>
        </receiver>
        <receiver android:name=".TestReceiver3">
            <intent-filter>
                <action android:name="com.cd.broadcastreceiver"></action>
            </intent-filter>
        </receiver>

这里三个接收者都是设置的相同的ACTION.

发送代码不变,点击按钮输出如下

这里写图片描述

三个都接收到了,而且输出顺序是按照AndroidMainifest注册顺序输出的,不确定这两者之间有没有关系,知道的麻烦告诉我一声。

接着我在第一个广播的onReceiver 方法中添加了abortBroadcast();终止广播。

这里写图片描述

再次运行,输出如下
这里写图片描述

还是接收到了,表明接收者不能终止广播,注意到在abortBroadcast的地方报了个错,这个先不管,

那么如何终止广播或者在广播传播的过程中修改广播内容呢?可以使用有序广播

有序广播每次只发送到优先级高的那里,然后由优先级高的依次往优先级低的发送,优先级高的可以决定终止或继续传播这个广播。
修改之前三个接收者的代码如下

第一个广播TestReceiver

public class TestReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String sky = intent.getStringExtra("sky");
        Log.d("TestReceiver", "接收到的值" + sky);
        Bundle bundle=new Bundle();
        bundle.putString("message",sky+"from TestReceiver");
        setResultExtras(bundle);
    }
}

第二个广播TestReceiver2

public class TestReceiver2 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String sky = getResultExtras(true).getString("sky");
        Log.d("TestReceiver2", "接收到的值" + sky);
        Bundle bundle=new Bundle();
        bundle.putString("message",sky+"message from TestReceiver2");
        setResultExtras(bundle);
    }
}

第三个广播TestReceiver3

public class TestReceiver3 extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String sky = getResultExtras(true).getString("sky");
        Log.d("TestReceiver3", "接收到的值" + sky);

    }
}

通过setResultExtras写入数据,getResultExtras获取数据

AndroidMainifest修改如下

<!--<receiver android:name=".TestReceiver"/>-->
        <receiver android:name=".TestReceiver"
            >
            <intent-filter android:priority="10">
                <action android:name="com.cd.broadcastreceiver"></action>
            </intent-filter>
        </receiver>
        <receiver android:name=".TestReceiver2">
            <intent-filter android:priority="9">
                <action android:name="com.cd.broadcastreceiver"></action>
            </intent-filter>
        </receiver>
        <receiver android:name=".TestReceiver3">
            <intent-filter android:priority="8">
                <action android:name="com.cd.broadcastreceiver"></action>
            </intent-filter>
        </receiver>

注意到,在intent-filter标签下,添加了android:priority属性,这是是设置广播的优先级,取值范围是-1000~1000,值越大,优先级越高,如果没有设置优先级会报这个错

BroadcastReceiver trying to return result during a non-ordered broadcast

而且只有第一个声明的能接收到,后面的无法接收。
修改发送广播的代码

 Intent intent1 = new Intent();
                intent1.setAction(ACTION);
                intent1.putExtra("sky","register in AndroidMainifest");
                sendOrderedBroadcast(intent1,null);

sendBroadcast改为sendOrderedBroadcast,这里多了一个权限参数,null表示不用权限,想了解权限可看这篇文章Android声明和使用权限

修改完,点击按钮输出为

这里写图片描述

由图可以看到,接收顺序是按照优先级来执行的,以及传递的值也是依次接收到了,【这里有个疑问,在输出的最后一行,第一个广播又输出了一次,这个很不可思议,不是广播在onReceive方法执行完后,实例就被摧毁了么,为什么会执行两次呢?如果有人看到这篇文章,并且知道造成的原因,麻烦告诉我一下,谢谢】

现在再次在TestReceiver的onReceiver中调用abortBroadcast();
输出如下
这里写图片描述
可以看到,优先级高的接收到了广播,后面优先级低的就被终止了,而且没有报之前那个错了。所以abortBroadcast要在有序广播中使用。

参考:
http://www.jianshu.com/p/903e08cba4b6

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值