Android的广播使用

来源:互联网 发布:索尼手机 知乎 编辑:程序博客网 时间:2024/05/16 10:01
 
  • 原文地址:http://www.it165.net/pro/html/201408/20532.html

  • 广是一种广泛运用在应用程序之间传输信息的机制,android中的广播用于监听系统事件或应用程序事件!android中的广播包括普通广播、有序广播以及异步广播(粘性广播)!

    广播又有常驻型广播和非常驻型广播,常驻型广播是在xml中进行注册的,当应用程序关闭后,如果有对应的广播发送过来,广播接收器还是能够被激活;非常驻型广播是在代码中进行注册的,当应用程序关闭,广播也就取消了,我们可以在Activity中的onCreate或者onResume方法中注册广播,然后在onDestory或者onPause方法中取消注册广播;

    注意:如果是非常驻型广播,应用程序关闭后,必须取消注册广播,否则会抛出异常!!

    普通广播的发送

    普通广播的发送使用方式:

    sendBroadcast(Intent intent):intent表示意图,所有匹配该广播的意图都能收到该广播信息

    sendBroadcast(intent, String receiverPermission);intent与上面一样,receiverPermission表示权限,与之匹配权限的广播才能接收到相应的广播,如果为null,表示不经许可的要求!

    一、使用sendBroadcast(Intent intent)发送广播

    1)通过代码注册非常驻型广播:

    view sourceprint?
    01.//定义两个广播接收者
    02.BroadcastReceiver receiver1=new BroadcastReceiver() {
    03.@Override
    04.public void onReceive(Context context, Intent intent) {
    05.System.out.println("receiver1 started!");
    06.}
    07.};
    08.BroadcastReceiver receiver2=new BroadcastReceiver() {
    09.@Override
    10.public void onReceive(Context context, Intent intent) {
    11.System.out.println("receiver2 started!");
    12.}
    13.};
    14. 
    15.@Override
    16.protected void onCreate(Bundle savedInstanceState) {
    17.super.onCreate(savedInstanceState);
    18.//注册广播
    19.IntentFilter filter=new IntentFilter();
    20.filter.addAction("com.xin.action.broadcast");
    21.registerReceiver(receiver1, filter);
    22.registerReceiver(receiver2, filter);
    23.}
    24. 
    25.@Override
    26.protected void onPause() {
    27.super.onPause();
    28.//取消注册广播
    29.unregisterReceiver(receiver1);
    30.unregisterReceiver(receiver2);
    31.}
    代码注册属于非常驻型广播,我们需在Activity相应的生命周期中取消注册广播:unregisterReceiver

    2)通过xml文件注册常驻型广播,此时的MyBroadcast1、MyBroadcast2为两个广播类:

    view sourceprint?
    1.public class MyBroadcast1 extends BroadcastReceiver{
    2. 
    3.@Override
    4.public void onReceive(Context context, Intent intent) {
    5.System.out.println("MyBroadcast1 started!");
    6.}
    7.}
    view sourceprint?
    1.public class MyBroadcast2 extends BroadcastReceiver{
    2. 
    3.@Override
    4.public void onReceive(Context context, Intent intent) {
    5.System.out.println("MyBroadcast2 started!");
    6.}
    7.}

    在AndroidManifest.xml中的application中添加:

    view sourceprint?
    01.<receiver android:name=".MyBroadcast1">
    02.<intent-filter>
    03.<action android:name="com.xin.action.broadcast"/>
    04.</intent-filter>
    05.</receiver>
    06.<receiver android:name=".MyBroadcast2">
    07.<intent-filter>
    08.<action android:name="com.xin.action.broadcast"/>
    09.</intent-filter>
    10.</receiver>
    代码中的IntentFilter和xml文件中的intent-filter是一样的,都是Intent意图,表示Intent(String actionName)发送出去的广播能被哪些广播接收者所接收!

    3)广播的发送:与之匹配的intent意图的广播将被激活

    view sourceprint?
    1.Intent intent=new Intent("com.xin.action.broadcast");
    2.sendBroadcast(intent);
    输出结果为:MyBroadcast1 started,MyBroadcast2 started!!

    二、使用sendBroadcast(intent, String receiverPermission)发送广播

    第二个参数的介绍如上面所示,指的是一个权限,我们需在AndroidManifest.xml中声明一个权限:

    view sourceprint?
    1.<permission android:name="com.xin.permission" android:protectionLevel="normal"/>
    里面还有很多的属性可供我们选择,大家可以去自己去了解一下;

    然后我们的发送广播方和接收广播方都需要该权限定义:

    发送广播方使用该权限:

    view sourceprint?
    1.<uses-permission android:name="com.xin.permission"/>
    通过方法发送广播:sendBroadcast(intent,"com.xin.permission");其中第二个参数表示我们定义的权限name

    接收方声明广播权限:

    view sourceprint?
    1.<receiver android:name=".MyBroadcast1" android:permission="com.xin.permission">
    2.<intent-filter>
    3.<action android:name="com.xin.action.broadcast"/>
    4.</intent-filter>
    5.</receiver>
    这样,使用带权限的广播就定义好了,我们在发送方和接收方都需要给权限进行定义,否则消息发送不过去!

    注意,通过sendBroadcast(intent,"com.xin.permission");发送的广播,并不一定需要在receiver中添加android:permission才能接收到,测试发现,没有添加这个也能接收到:

    view sourceprint?
    1.<receiver android:name=".MyBroadcast2">
    2.<intent-filter>
    3.<action android:name="com.xin.action.broadcast"/>
    4.</intent-filter>
    5.</receiver>

    有序广播的发送

    顾名思义,有序广播就是广播的发送是按照顺序进行的,它根据优先级别的定义android:priority的高低来进行有序发送,一个接受完发给下一个接收,优先级越高,表示它接收到的广播级别高,android:priority的范围一般是在-1000到1000之间;
    有序广播和普通广播之间的区别:

    有序广播和无序广播的区别:我们发送完无序广播之后,我们不知道谁先接收谁后接收,更不要说当这个接收了之后不要再发给另外的了。而有序广播就可以做到这一点,它通过设置优先级可以决定广播接受者的顺序。

    有序广播的发送方式:

    sendOrderedBroadcast(intent, receiverPermission);

    sendOrderedBroadcast(intent, receiverPermission, resultReceiver,

    scheduler, initialCode, initialData, initialExtras)

    意图,广播,所有匹配的这一意图将接收机接收广播。

    receiverPermission 这是权限,一个接收器必须持以接收您的广播。如果为 null ,不经许可的要求。 
    resultReceiver 您自己 BroadcastReceiver 来当作最后的广播接收器。 
    调度自定义处理程序,用以安排 resultReceiver 回调 ; 如果为 null 将语境中的主线程举行。 
    initialCode 一种结果代码的初始值。通常为 Activity.RESULT_OK 。这个值是 -1 ;为其他 int 型 也可以,如 0,1,2; 
    initialData 一种结果数据的初始值。通常情况下为空 , 是 String 类型 ;
    initialExtras 一种结果额外的初始值。通常情况下为空 , 是 Bundle;

    有序广播需注意方面:

    1, 该广播的级别有级别之分,级别数值是在 -1000 到 1000 之间 , 值越大 , 优先级越高;
    2, 同级别接收是先后是随机的,再到级别低的收到广播;
    3, 同级别接收是先后是随机的,如果先接收到的把广播截断了,同级别的例外的接收者是无法收到该广播的,截断广播的方式:abortBroadcast() ;
    4 ,能截断广播的继续传播,高级别的广播收到该广播后,可以决定把该钟广播是否截断掉。
    5 ,实验现象,在这个方法发来的广播中,代码注册方式中,收到广播先后次序为:注明优先级的、代码
    代码演示:

    下面给大家演示一下发送有序广播,并且通过Intent在广播之间传递数据,因为关于权限那块上面已经说了,所以在有序广播这里就不再描述了,通过sendOrderedBroadcast(intent, receiverPermission);方法发送有序广播,第二个参数就设置为null了:这里我们通过xml注册广播

    1)定义广播

    view sourceprint?
    01.public class MyBroadcast2 extends BroadcastReceiver{
    02.@Override
    03.public void onReceive(Context context, Intent intent) {
    04.System.out.println("MyBroadcast2 started!");
    05.//接收sendOrderedBroadcast传递过来的Intent中的参数
    06.System.out.println(intent.getStringExtra("test"));
    07.//添加另一个参数
    08.Bundle bundle=new Bundle();
    09.bundle.putString("test2""我是从MyBroadcast2中存储的数据");
    10.//将其封装为Bundle对象,让下一个广播接收
    11.setResultExtras(bundle);
    12.}
    13.}
    view sourceprint?
    01.public class MyBroadcast1 extends BroadcastReceiver{
    02. 
    03.@Override
    04.public void onReceive(Context context, Intent intent) {
    05.System.out.println("MyBroadcast started!");
    06.//接收sendOrderedBroadcast传递过来的Intent中的参数
    07.System.out.println(intent.getStringExtra("test"));
    08.//得到从上一个广播中携带过来的另一个数据
    09.Bundle bundle=getResultExtras(true);
    10.System.out.println(bundle.getString("test2"));
    11.}
    12.}
    2)在AndroidManifest.xml中声明广播:

    view sourceprint?
    01.<receiver android:name=".MyBroadcast1">
    02.<intent-filter android:priority="900">
    03.<action android:name="com.xin.action.broadcast"/>
    04.</intent-filter>
    05.</receiver>
    06.<receiver android:name=".MyBroadcast2">
    07.<intent-filter android:priority="1000">
    08.<action android:name="com.xin.action.broadcast"/>
    09.</intent-filter>
    上面声明的广播中,MyBroadcast2比Mybroadcast1的优先级高!

    3)发送有序广播

    view sourceprint?
    1.Intent intent=new Intent("com.xin.action.broadcast");
    2.intent.putExtra("test""我是sendOrderedBroadcast发送过来的数据!");
    3.sendOrderedBroadcast(intent,null);
    测试结果:

    \

    因为Mybroadcast2的优先级(1000)比Mybroadcast1(900)的高,所以广播通过sendOrderedBroadcast发送出去后,首先被Mybroadcast2接收,然后再Mybroadcast2中通过setResultExtras设置了另一些参数一起传到Mybroadcast1,然后Mybroadcast1接收到广播,也通过getResultExtras(true)接收从Mybroadcast2中携带过来的数据,所以出现上面的结果!

    经测试发现,在使用sendBroadcast时候,如果在BroadcastReceiver中使用setResultExtras或者getResultExtras,程序会报错,因为它发送的不是有序广播!

    注意:
    1、如果是在代码中注册的,我们可以通过filter.setPriority(1000);来设置其优先级,这里就不举例说明了!

    2、如果我们想让有序广播在一个BroadcastReceiver中接收后,不再往下一个广播执行,可以调用其abortBroadcast();中断广播的发送,后面的广播将接收不到!

    粘性广播(异步广播)的发送

    在网上专业名称各不一样,有人讲它是粘性广播,也有人说它是异步广播,先不讨论它的专业名词的问题了,先来让我们了解它有什么用,它与普通广播的区别就是当广播取消注册后,然后发送一个粘性广播,广播重新注册后仍然能接收到粘性广播发送过来的消息!

    普通广播与粘性广播最大的区别:

    我们知道,我们先注册广播,然后发送广播,那么无论是什么广播都能被接收到,那么如果我们先发送广播,后注册广播呢:

    普通广播:未注册广播-->发送广播-->注册广播-->接收不到广播

    粘性广播:未注册广播-->发送广播-->注册广播-->能接收到广播,并且能接收到多次发送广播的最后一条广播信息

    这就是两者之间的区别,下面我们通过代码的方式给大家举一个例子,我们的广播是在代码中注册的非常驻型广播:

    页面只包含三个测试按钮:

    \

    我们在注册广播的Activity中注册广播:RegisterActivity,在其生命周期的onPause方法中取消注册广播unregisterBr

    view sourceprint?
    01.//定义广播
    02.BroadcastReceiver receiver=new BroadcastReceiver() {
    03.@Override
    04.public void onReceive(Context context, Intent intent) {
    05.String action=intent.getAction();
    06.int count=intent.getIntExtra("count"0);
    07.System.out.println("action="+action+",count="+count);
    08.}
    09.};
    10. 
    11.//注册广播
    12.@Override
    13.protected void onCreate(Bundle savedInstanceState) {
    14.super.onCreate(savedInstanceState);
    15.setContentView(R.layout.register);
    16.IntentFilter filter=new IntentFilter();
    17.//添加广播Action
    18.filter.addAction("com.xin.action.broadcast");
    19.filter.addAction("com.xin.action.sticky.broadcast");
    20.registerReceiver(receiver, filter);
    21.}
    22. 
    23.//取消注册广播
    24.@Override
    25.protected void onPause() {
    26.super.onPause();
    27.System.out.println("RegisterBroadActivity onPause!");
    28.unregisterReceiver(receiver);
    29.}
    在MainActivity中发送广播:

    view sourceprint?
    01.//定义一个变量,来统计点击发送粘性广播的次数,然后测试粘性广播的接收是不是最后一条广播
    02.private int count;
    03.@Override
    04.public void onClick(View v) {
    05.Intent intent=null;
    06.switch(v.getId()){
    07.case R.id.btn_send1://发出广播sendBroadcast
    08.intent=new Intent("com.xin.action.broadcast");
    09.sendBroadcast(intent);
    10.break;
    11.case R.id.btn_send2://发出粘性广播sendStickyBroadcast
    12.count++;
    13.intent=new Intent("com.xin.action.sticky.broadcast");
    14.intent.putExtra("count", count);
    15.sendStickyBroadcast(intent);
    16.break;
    17.case R.id.register://启动注册广播页面
    18.intent=new Intent(MainActivity.this,RegisterBroadActivity.class);
    19.startActivity(intent);
    20.break;
    21.}
    22.}
    23. 
    24.@Override
    25.protected void onResume() {
    26.super.onResume();
    27.count=0;
    28.System.out.println("MainActivity onResume!");
    29.}
    注意,发送粘性广播,我们需要在AndroidManifest.xml中添加能够发送粘性广播的权限,否则会报错:

    view sourceprint?
    1.<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
    测试及结论:

    当我们点击发送sendBroadcast按钮3次--点击注册按钮,控制台无输出结果

    当我们点击发送sendStickyBroadcast按钮4次--点击注册按钮,控制台输出结果:action=com.xin.action.sticky.broadcast,count=4

    这就是普通广播和粘性广播的区别
    sendBroadcast发送出去的广播,如果没有广播进行注册,那么该广告也就接收不到了,当重新注册广播后,也接收不到
    sendStickyBroadcast发送出去的广播,如果没有广播进行注册,那么该广告此时也就接收不到了,当重新注册广播后,会接收到,并且会接受sendStickyBroadcast发出去的最后一条广播,所以上面的输出结果中点击发送stickybroadcast 4次,count变为4,那么当重新注册广播后,控制台会输出结果count=4;
    sendStickyBroadcast发出的最后一个Intent会被保留,下次当Recevier处于活跃的 时候,又会接受到它。

    当我们需要移除掉粘性广播的时候,调用方法:removeStickyBroadcast(intent);即可清除掉粘性广播

    还有一个发送广播的方式:sendStickyOrderedBroadcast (),测试在这个方法发来的广播,代码注册方式中,收到广播先后次序为:注明优先级的、代码注册的、没有优先级的;如果都没有优先级,代码注册收到为最先。

    上面给大家介绍了广播操作中的几种方式:

    发送广播:sendBroadcast(Intent intent)、sendBroadcast(Intent intent,String receiverPermission);

    发送有序广播:sendOrderedBroadcast(Intent intent,String receiverPermission);

    发送粘性广播:sendStickyBroadcast(Intent intent);

    还有一种方式:sendStickyOrderedBroadcast();(未研究,不知道用的多不多)

    在Android的广播操作中,我们还应该知道:

    1、无论对于有序广播还是无序广播,广播接收器默认都是运行在主线程中的(main线程,即UI线程)。可以通过在程序中使用registerReceiver(receiver, filter, broadcastPermission, scheduler)方法中的最后一个参数指定要运行的广播接收器的线程。也可以在Manifest.xml文件中设置(Intent-filter标签中设置android:process)。

    2、我们在代码中注册广播registerBroadcast十次,那么广播发送过来的时候会接收十次,注销广播只需一次!

    3、每次广播到来时 , 会重新创建 BroadcastReceiver 对象 , 并且调用 onReceive() 方法 , 执行完以后 , 该对象即被销毁 . 当 onReceive() 方法在 10 秒内没有执行完毕, Android 会认为该程序无响应 . 所以在BroadcastReceiver 里不能做一些比较耗时的操作 , 否侧会弹出 ANR(Application NoResponse) 的对话框,如果需要完成一项比较耗时的工作 , 应该通过发送 Intent 给 Service, 由 Service 来完成 . 这里不能使用子线程来解决 , 因为 BroadcastReceiver 的生命周期很短 , 子线程可能还没有结束BroadcastReceiver 就先结束了 .BroadcastReceiver 一旦结束 , 此时 BroadcastReceiver 的所在进程很容易在系统需要内存时被优先杀死 , 因为它属于空进程 ( 没有任何活动组件的进程 ). 如果它的宿主进程被杀死 , 那么正在工作的子线程也会被杀死 . 所以采用子线程来解决是不可靠的 .

    4、耗时的操作应该通过广播启动service来执行操作

    view sourceprint?
    1.BroadcastReceiver receiver=new BroadcastReceiver() {
    2.@Override
    3.public void onReceive(Context context, Intent intent) {
    4.Intent intent=new Intent(context,TestService.class);
    5.startService(intent);
    6.}
    7.};
0 0
原创粉丝点击