Android复习之BroadCastReceiver
2016-10-20 23:29
97 查看
是什么
BroadCastReceiver是四大组件之一,相当于一个全局的监听器,用于监听系统全局的广播。怎么样
由于BroadCastReceiver是全局监听器,因此它可以方便的实现系统中不同组件之间的通信。怎么用
实现步骤分三步
创建BroadCastReceiver创建需要启动BroadCastReceiver的Intent
调用Context的sendBroadCast或sendOrderBroadCast方法启动指定的receiver
receiver需要继承BroadCastReceiver并实现onReceive方法,当程序发出一个BroadCast的Intent之后所有匹配了改Intent的BroadCastreceover都有可能会被启动
与Activity和Service不同的是BroadCastReceiver生命周期比较短,本质是一个系统级全局的监听器,专门负责监听个程序所发出的BroadCast
实现了BroadCastReceive就要有与只匹配的Intent
两种匹配intent方式
在代码中动态设置,通过intentFilter设置Action在AndroidMainifest中的receiver标签中设置Action
值得注意的是:
执行完onReceiver后实例会被销毁,生命周期短发送广播后如果没有与之匹配的receiver,程序不会报错,这与Activity和Service不同
不能在onReceiver方法中做耗时操作,10秒内onReceive方法没有执行完成会被认为程序无响应,因此耗时操作应该在Service中开启线程来执行
两种发送广播的方式
sendBroadCast()普通广播sendOrderBroadCast()有序广播
有序广播会根据优先级别按顺序执行接收者,优先接到的可通过abortBroadCast来终止广播,也可以通过setResultExtra()来修改接收到的值并传递,下一个广播在通过getResultExtra()来获取。
两种注册方式
动态注册,广播会跟随程序的生命周期,在Activity或service中注册,但是必须到onDestroy中销毁,不然会报错静态注册,常驻型,即使应用关闭,也能够接收广播
代码演示
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就是接收传过来的值
第二步,创建匹配该
broadCastReceiver的
Intent,首先要给
broadCastReceiver设置一个Action,然后再通过给Intent设置Action,如果Intent的Action与
broadCastReceiver的Action匹配,也就是一样,则
broadCastReceiver将会被系统启动,接收到Intent传过来的消息。首先注册广播,由上面可知注册有动态注册和静态注册,
动态注册代码
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会不会都收到,或者多个接收者之间有没有相互的影响呢?
在上面的基础上添加另外两个接收者
TestReceiver2和
TestReceiver3,然后我选择静态注册
<!--<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
相关文章推荐
- Android 复习_Service 二
- AndroidUI组件学习(2)复习
- Android面试准备复习之Android知识点大扫描 .
- Android面试知识点复习
- android 整体复习笔记(一)
- Android控件复习:按钮(Button)
- Android面试准备复习之Android知识点大扫描 .
- Android 复习 listview中的几个参数的含义
- Android学习第九天----java复习集合
- Android复习:Activity
- android基础知识复习(一)——对话框风格的Activity、Menu、Activity生命周期
- Android之Service复习深入
- Android基础复习2D图形二
- android基础知识复习(二)——RelativeLayout布局属性、背景、半透明设置(XML设置)
- JAVA相关基础知识(复习java,为的就是搞android)
- Android 复习_Task 与 Back Stack
- Android 复习 Content Provider
- Android之Service复习深入
- Android 之 复习大纲
- 2013年7月17日 19:57:12 android复习1