BroadcastReceiver详解(基础篇)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BroadcastReceiver详解(基础篇)相关的知识,希望对你有一定的参考价值。
参考技术ABroadcast (广播)是一种广泛运用的应用程序之间传输信息的机制,而 BroadcastReceiver (广播接收器)则是用于接收来自系统和应用的广播对并对其进行响应的组件,android中我们要发送的广播内容是一个 Intent ,这个 Intent 中可以携带我们要传送的数据
创建一个广播接收器非常简单,只需要继承 BroadcastReceiver ,并重写 onReceive() 即可
BroadcastReceiver 也是四大组件之一,所以我们也需要对 BroadcastReceiver 进行注册,不同于其他四大组件, BroadcastReceiver 有两种注册方式,分别是 静态注册 和 动态注册
静态注册
当我们的应用首次启动的时候,系统会自动实例化我们静态注册的 BroadcastReceiver ,然后将这个 BroadcastReceiver 注册到系统中,系统接收到广播之后,就会做出相应的判断,调用 onReceive() 方法。通过这种方式注册的广播,即使我们的应用被销毁,依然能收到广播。 这里要注意的是,我们的应用一定要被启动过 ,如果没有被启动可能就无法接收到广播,可以参考文章 Android应用在未启动的情况下无法收到指定广播的问题总结
正是因为静态注册耗电、占内存、不受程序生命周期影响,所以Google在Android 8.0上禁止大部分广播的静态注册,可以参考官文文档 Android 8.0 功能和 API
动态注册
通过动态注册的广播, BroadcastReceiver 的生命周期跟随Activity的生命周期
注意: 要在 Activity 的 onPause() 中 unRegeisterReceiver() ,否则会引起内存泄漏。比较推荐 onResume() 中去注册广播,在 onPause() 中去注销广播。因为在内存资源比较吃紧的情况下,可能我们的 Activity 执行完 onPause() 之后就被销毁,这时候 Activity 的 onStop() 和 onDestory() 方法就不会执行了
BroadcastReceiver注册完之后,这个 BroadcastReceiver 就能够接收响应的广播,下面我们来说说如何发送一条广播
普通广播(Normal Broadcast)
普通广播完全是异步的,通过 context.sendBroadcast() 方法发送,消息传递效率比较高,但所有接收器的执行顺序不确定。缺点是接收者不能将处理结果传递给下一个接收者,并且无法终止广播的传播
有序广播(Ordered Broadcast)
有序广播是通过 context.sendOrderedBroadcast() 方法发送,所有的广播者按照优先级依次执行,广播接收器的优先级通过 receiver 的 intent-filter 中的 android:priority 属性来设置,数值越大优先级越高。当广播接收器接收到广播后,可以使用 setResult() 方法把结果传递给下一个接收者,通过 getResult() 方法获取上一个接收者传递过来的结果,并可以通过 abortBroadcast() 方法丢弃该广播,使该广播不再传递给下一个接收者
粘性广播(Sticky Broadcast)
粘性广播通过 context.sendStickBroadcast() 方法来发送,用此方法发送的广播会一直滞留,当有匹配此广播的接收器被注册后,该广播接收器就会收到此广播。使用此广播时,需要获得 BROADCAST_STICKY 权限
由于在Android5.0 & API 21中已经失效,所以不建议使用。
本地广播(Local Broadcast)
前三种广播都是全局广播,所有应用都可以接收到,这样就带来安全隐患,而本地广播只在进程内传播,可以起到保护数据安全的作用
其实,本地广播的使用与其十分类似,之前的步骤均是一样的,调用者不同而已,本地广播调用的是 LocalBroadcastManager 相关方法,全局广播调用的是 Context 的相关方法,其方法名都是一样的
这里需要说一下, 使用本地广播并没有静态注册的方法 ,因为静态注册主要是为了让程序在未启动的情况下也能收到广播,而发动本地广播的时候,我们的程序已经是启动了,所以,自然是没有静态注册这个方法
Android中内置了多个系统广播,当使用系统广播时,只需要在注册广播接收者时定义相关的 action 即可,并不需要手动发送广播,当系统有相关操作(如开机、网络状态变化、拍照等等)时会自动进行系统广播
Android系统广播 action 如下:
本文介绍了 BroadcastReceiver 的两种注册方式(动态注册、静态注册),四种发送方式(普通广播、有序广播、粘性广播(API21废弃)、本地广播),以及系统广播的用法。几乎涵盖了 BoradcastReceiver 在应用开发过程中的所有知识,对于BroadcastReceiver原理感兴趣的可以继续看 BroadcastReceiver详解(原理篇)
Android中广播接收者BroadcastReceiver详解
1. 接收系统的广播步骤
(1) 新建一个类继承BroadcastReceiver
以监听sd卡状态的广播接收者为例
1 public class SdCardBroadcastReceiver extends BroadcastReceiver { 2 3 @Override 4 public void onReceive(Context context, Intent intent) { 5 String action = intent.getAction(); 6 if("android.intent.action.MEDIA_MOUNTED".equals(action)){ 7 System.out.println("sd卡已挂载"); 8 }else if("android.intent.action.MEDIA_UNMOUNTED".equals(action)){ 9 System.out.println("sd卡已卸载"); 10 } 11 } 12 13 }
形象一点的比喻, 这一步相当于买了个收音机
(2) 在清单文件中注册
1 <!-- 相当于装电池 --> 2 <receiver android:name="com.example.sdbroadcast.SdCardBroadcastReceiver"> 3 <!-- 相当于调频道 --> 4 <intent-filter> 5 <action android:name="android.intent.action.MEDIA_MOUNTED"/> 6 <action android:name="android.intent.action.MEDIA_UNMOUNTED"/> 7 <data android:scheme="file"/> 8 </intent-filter> 9 </receiver>
这一步相当于装电池
(3) 在清单文件中添加意图过滤器,action里写监听的内容
1 <!-- 相当于调频道 --> 2 <intent-filter> 3 <action android:name="android.intent.action.MEDIA_MOUNTED"/> 4 <action android:name="android.intent.action.MEDIA_UNMOUNTED"/> 5 <data android:scheme="file"/> 6 </intent-filter>
这一步相当于调频道了
2. 发送自定义的无序广播
(1) 发送广播
1 public void startBroadcast(View view){ 2 //开启广播 3 //创建一个意图对象 4 Intent intent = new Intent(); 5 //指定发送广播的频道 6 intent.setAction("com.example.BROADCAST"); 7 //发送广播的数据 8 intent.putExtra("key", "发送无序广播,顺便传递的数据"); 9 //发送 10 sendBroadcast(intent); 11 }
(2) 接收广播
新建一个类,继承BroadcastReceiver
1 public class UnorderedReceiver extends BroadcastReceiver { 2 3 @Override 4 public void onReceive(Context context, Intent intent) { 5 String action = intent.getAction(); 6 7 String data = intent.getStringExtra("key"); 8 9 System.out.println("接受到了广播,action:"+ action +",data:"+data); 10 11 //接受到了广播,action:com.example.BROADCAST,data:发送无序广播,顺便传递的数据 12 } 13 14 }
记得在清单文件中进行注册
1 <receiver android:name="com.example.selfreceiver.UnorderedReceiver"> 2 <intent-filter> 3 <action android:name="com.example.BROADCAST"/> 4 </intent-filter> 5 </receiver>
打印出的结果:
3. 发送自定义的有序广播
(1) 发送广播
1 // 发送有序广播 2 public void sendOrderedBroad(View view) { 3 Intent intent = new Intent(); 4 intent.setAction("com.example.ORDERED"); 5 // 发送无序广播 6 sendOrderedBroadcast(intent,//意图动作,指定action动作 7 null, //receiverPermission,接收这条广播具备什么权限 8 new FinalReceiver(),//resultReceiver,最终的广播接受者,广播一定会传给他 9 null, //scheduler,handler对象处理广播的分发 10 0,//initialCode,初始代码 11 "每人发10斤大米,不得有误!", //initialData,初始数据 12 null//initialExtras,额外的数据,如果觉得初始数据不够,可以通过bundle来指定其他数据 13 ); 14 }
在上面的代码中,广播发送者发送了一条广播:"每人发10斤大米,不得有误!"
(2) 接收广播
新建一个类, 继承BroadcastReceiver,并在清单文件中进行注册
以下是所有的广播接收者在清单文件中的注册
权限从-1000 至 1000
1) 权限高的广播接收者可以修改广播,甚至可以终止广播
权限高的广播接收者1:
1 public class ShengReceiver extends BroadcastReceiver { 2 3 @Override 4 public void onReceive(Context context, Intent intent) { 5 6 //获取广播的数据 7 String data = getResultData(); 8 9 //修改 10 setResultData("中央下达福利,每人5斤大米"); 11 12 System.out.println("省政府收到指示, data : "+data); 13 } 14 15 }
在这里, 这个接收者修改广播为: "中央下达福利,每人5斤大米"
权限低的广播接收者
1 public class PeopleReceiver extends BroadcastReceiver { 2 3 @Override 4 public void onReceive(Context context, Intent intent) { 5 //获取广播的数据 6 String data = getResultData(); 7 System.out.println("老百姓收到福利,感谢党, data : "+data); 8 } 9 10 }
这样,在控制台打印出来的信息为:
权限低的接收者 接收到的广播就是修改后的了
2) 终止广播
权限高的广播接收者:
1 public class ShengReceiver extends BroadcastReceiver { 2 3 @Override 4 public void onReceive(Context context, Intent intent) { 5 6 //获取广播的数据 7 String data = getResultData(); 8 9 //也可以终止广播,权限小的接收者就接收不到广播了 10 abortBroadcast(); 11 12 System.out.println("省政府收到指示, data : "+data); 13 } 14 15 }
控制台打印:
权限小的就接收不到广播了....
(3) resultReceiver
可以在广播发送者的应用中建一个resultReceiver, 用于接收最终到达的广播,
无论广播是否终止,都会被resultReceiver接收
1 public class FinalReceiver extends BroadcastReceiver { 2 3 @Override 4 public void onReceive(Context context, Intent intent) { 5 String resultData = getResultData(); 6 System.out.println("人民收到的最终福利是: "+ resultData); 7 } 8 9 }
控制台打印信息:
(终止广播后):
(修改广播后):
4. 补充:
有序广播和无序广播的区别:
有序广播:发送方发出后,几乎同时到达多个广播接收者处,某个接收者不能接收到广播后进行一番处理后传给下一个接收者,并且无法终止广播继续传播;Context.sendBroadcast(intent);
有序广播:广播接收者需要提前设置优先级,优先级高的先接收到广播,优先级数值为-1000~1000,在AndroidManifest.xml的<intent-filter android:priority="xxx">设置;比如存在3个广播接收者A、B、C,优先级A>B>C,因此A最先收到广播,当A收到广播后,可以向广播中添加一些数据给下一个接收者(intent.putExtra()),或者终止广播(abortBroadcast());Context.sendOrderedBroadcast(intent);
以上是关于BroadcastReceiver详解(基础篇)的主要内容,如果未能解决你的问题,请参考以下文章