Android四大组件之一 BroadcastReceiver解析
来源:互联网 发布:绫致时装官方店淘宝 编辑:程序博客网 时间:2024/05/19 22:50
继上一篇讲完Service后,现在来详述下Android中的广播,笔者也是自己的一点经验之谈,如果有错误,请在评论区指出。具体代码可见https://github.com/Mangosir/BroadcastReview
广播是Android四大组件之一,这也说明了它的重要性,那什么是广播呢,有哪些分类呢,有哪些注册方式,具体该怎么用呢,接下来一一道来。
概述
在Android中,Broadcast是一种广泛运用在应用程序之间(单进程通信或者进程间通信)传输信息的机制。而BroadcastReceiver是一个专注于接收广播通知信息,并做出对应处理的组件。很多广播是源自于系统的─比如,通知时区改变、电池电量低、拍摄了一张照片或者用户改变了语言选项。应用程序也可以进行广播──比如说,通知其它应用程序一些数据下载完成并处于可用状态。
应用程序可以拥有任意数量的广播接收器以对所有它感兴趣的通知信息予以响应。所有的接收器均继承自BroadcastReceiver基类。
广播接收器没有用户界面。然而,它们可以启动一个activity来响应它们收到的信息,或者用NotificationManager来通知用户。通知可以用很多种方式来吸引用户的注意力──闪动背灯、震动、播放声音等等。
分类
Android中的广播主要分为一下类型:
1.普通广播(Normal Boradcast):
开发者自己定义的Intent,具体可以使用的方法有:
sendBroadcast(intent)/sendBroadcast(intent,receiverPermission)/sendBroadcastAsUser(intent,userHandler)/sendBroadcastAsUser(intent, userHandler,receiverPermission)。
2.系统广播(System Boradcast):
Android系统中内置了多个系统广播,只要涉及到手机的基本操作,基本上都会发出相应的系统广播。如:开启启动,网络状态改变,拍照,屏幕关闭与开启,点亮不足等等。每个系统广播都具有特定的intent-filter,其中主要包括具体的action,系统广播发出后,将被相应的BroadcastReceiver接收。系统广播在系统内部当特定事件发生时,有系统自动发出。
3.有序广播(Ordered Boradcast):
有序广播中的“有序”是针对广播接收者而言的,指的是发送出去的广播被BroadcastReceiver按照先后循序接收。有序广播的定义过程与普通广播无异,只是其主要发送方式变为:sendOrderedBroadcast(intent, receiverPermission, ...)。
对于有序广播,其主要特点总结如下:
1>多个具当前已经注册且有效的BroadcastReceiver接收有序广播时,是按照先后顺序接收的,先后顺序判定标准遵循为:将当前系统中所有有效的动态注册和静态注册的BroadcastReceiver按照priority属性值从大到小排序,对于具有相同的priority的动态广播和静态广播,动态广播会排在前面。
2>先接收的BroadcastReceiver可以对此有序广播进行截断,使后面的BroadcastReceiver不再接收到此广播,也可以对广播进行修改,使后面的BroadcastReceiver接收到广播后解析得到错误的参数值。当然,一般情况下,不建议对有序广播进行此类操作,尤其是针对系统中的有序广播。
4.本地广播(Local Boradcast):
BroadcastReceiver设计的初衷是从全局考虑可以方便应用程序和系统、应用程序之间、应用程序内的通信,所以对单个应用程序而言BroadcastReceiver是存在安全性问题。
可能出现安全隐患如下:1.其他App可能会针对性的发出与当前App intent-filter相匹配的广播,由此导致当前App不断接收到广播并处理;
2.其他App可以注册与当前App一致的intent-filter用于接收广播,获取广播具体信息。
无论哪种情形,这些安全隐患都确实是存在的。由此,最常见的增加安全性的方案是:
1.对于同一App内部发送和接收广播,将exported属性人为设置成false,使得非本App内部发出的广播不被接收;
2.在广播发送和接收时,都增加上相应的permission,用于权限验证;
3.发送广播时,指定特定广播接收器所在的包名,具体是通过intent.setPackage(packageName)指定在,这样此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。
4.使用LocalBroadcastManager,即App应用内广播。
App应用内广播可以理解成一种局部广播的形式,广播的发送者和接收者都同属于一个App。实际的业务需求中,App应用内广播确实可能需要用到。同时,之所以使用应用内广播时,而不是使用全局广播的形式,更多的考虑到的是Android广播机制中的安全性问题。相比于全局广播。
App应用内广播优势体现在:
1、因广播数据在本应用范围内传播,你不用担心隐私数据泄露的问题。
2、不用担心别的应用伪造广播,造成安全隐患。
3、相比在系统内发送全局广播,它更高效
看看本地广播的源码
public static LocalBroadcastManager getInstance(Context context) { synchronized (mLock) { if (mInstance == null) { mInstance = new LocalBroadcastManager(context.getApplicationContext()); } return mInstance; }}private LocalBroadcastManager(Context context) { mAppContext = context; mHandler = new Handler(context.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_EXEC_PENDING_BROADCASTS: executePendingBroadcasts(); break; default: super.handleMessage(msg); } } };}
从这个部分源码可以看出两点:
1.在获取LocalBroadcastManager对象实例的时候,这里用了单例模式。并且把外部传进来的Context转化成了ApplicationContext,有效的避免了当前Context的内存泄漏的问题。这一点我们在设计单例模式框架的时候是值得学习的,看源码可以学习到很多东西。
2.在LocalBroadcastManager构造函数中创建了一个Handler.可见 LocalBroadcastManager的本质上是通过Handler机制发送和接收消息的。
3.在创建Handler的时候,用了context.getMainLooper() ,说明这个Handler是在Android主线程中创建的,广播接收器的接收消息的时候会在Android主线程,所以我们决不能在广播接收器里面做耗时操作,以免阻塞UI。
注册方式
1.静态注册:直接在Androidmanifest.xml中注册:
<receiver
android:exported=["true" |"false"]
android:name="string"
android:permission="string"
android:process="string" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
</intent-filter>
</receiver>
以上是一些注册属性,其中:android:exported ——此broadcastReceiver能否接收其他App的发出的广播,这个属性默认值有点意思,其默认值是由receiver中有无intent-filter决定的,如果有intent-filter,默认值为true,否则为false。(同样的,activity/service中的此属性默认值一样遵循此规则)同时,需要注意的是,这个值的设定是以application或者application user id为界的,而非进程为界(一个应用中可能含有多个进程);
android:name —— 此broadcastReceiver类名;
android:permission ——如果设置,具有相应权限的广播发送方发送的广播才能被此broadcastReceiver所接收;
android:process ——broadcastReceiver运行所处的进程。默认为app的进程。可以指定独立的进程(Android四大基本组件都可以通过此属性指定自己的独立进程)
intent-filter ——用于指定此广播接收器接收特定的广播类型
看注册样例:
<receiver android:name=".broadcast.BroadcastDemo"> <intent-filter > <action android:name="android.intent.action.ACTION_POWER_CONNECTED"></action> </intent-filter></receiver>可能有的同学还有这个印象,通过静态注册广播,即使应用退出了,广播接收器依然还在工作,收到相应广播后还会处理,但是Android 3.1开始,系统在Intent与广播相关的flag增加了参数,分别是
FLAG_INCLUDE_STOPPED_PACKAGES:包含已经停止的包(停止:即包所在的进程已经退出)FLAG_EXCLUDE_STOPPED_PACKAGES:不包含已经停止的包
系统本身则增加了对所有app当前是否处于运行状态的跟踪。在发送广播时,不管是什么广播类型,系统默认直接增加了值为FLAG_EXCLUDE_STOPPED_PACKAGES的flag,导致即使是静态注册的广播接收器,对于其所在进程已经退出的app,同样无法接收到广播。
BroadcastDemo broadcastDemo = new BroadcastDemo();IntentFilter intentFilter = new IntentFilter();intentFilter.addAction("com,mangoer.boradcast");registerReceiver(broadcastDemo,intentFilter);
其中BoradcastDemo是我自定义的一个广播,给这个广播加了一个过滤器IntentFilter,表示这个广播接收器只接受这个类型的广播。注册之后一定要记得取消注册
if (broadcastDemo != null) { unregisterReceiver(broadcastDemo);}
对于本地广播
注册方式不一样(本地广播只能通过代码中注册,不要在xml里注册)
LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);BroadcastDemo broadcastDemo = new BroadcastDemo();IntentFilter intentFilter = new IntentFilter();intentFilter.addAction("com,mangoer.boradcast");broadcastManager.registerReceiver(broadcastDemo,intentFilter);
取消注册也不一样
broadcastManager.unregisterReceiver(broadcastDemo);
两者发送广播方式也不一样
本地广播是
Intent intent = new Intent();intent.setAction("com,mangoer.boradcast");broadcastManager.sendBroadcast(intent);而非本地广播是
Intent intent = new Intent();intent.setAction("com,mangoer.boradcast");sendBroadcast(intent);
看对比
发送方式
1.sendBroadcast(Intent intent);
参数intent:携带Action标识信息(与注册广播是的IntentFilter中的action要相同)且可以携带数据
使用Context.sendBroadcast发送,如果依次注册了三个广播接收者A/B/C,那么接受顺序是C/B/A,即后注册的总是先收到广播
使用LocalBroadcastManager.sendBroadcast发送,如果依次注册了三个广播接收者A/B/C,那么接受顺序是A/B/C,即先注册的总是先收到广播
2.sendBroadcast(Intent intent, String receiverPermission)
参数intent:携带Action标识信息(与注册广播是的IntentFilter中的action要相同)且可以携带数据
参数receiverPermission:字面意思是指定广播接收者的权限,也就是说你的BroadcastReceiver注册的时候要添加了这个权限,后续才能收到这个广播
未完待续。。。
- Android四大组件之一---BroadcastReceiver全面解析
- Android四大组件之一 BroadcastReceiver解析
- Android 四大组件之一 BroadcastReceiver
- Android四大组件之一:BroadcastReceiver
- Android四大组件之一:BroadcastReceiver
- Android 四大组件之一BroadcastReceiver
- 【Android】四大组件之一:BroadcastReceiver
- BroadcastReceiver-四大组件之一
- 四大组件之一:BroadcastReceiver
- android 四大组件之一 BroadcastReceiver 广播接收者
- Android 四大组件之一:BroadcastReceiver广播机制
- 深入理解Android四大组件之一BroadcastReceiver
- BroadcastReceiver简单总结(android四大组件之一)
- Android四大组件之一 广播接收者 BroadcastReceiver
- Android四大组件之一BroadcastReceiver简析
- Android四大组件之BroadcastReceiver详细解析
- Android四大组件:BroadcastReceiver史上最全面解析
- Android四大组件:BroadcastReceiver史上最全面解析
- 理解矩阵1
- 算法
- Android原生音量控制
- Aspose.Total 套包组件介绍 | 附下载
- Java源码分析之HashMap(JDK1.8)
- Android四大组件之一 BroadcastReceiver解析
- 理解矩阵2
- 图像风格化总结
- android动画
- Apache服务器下ThinkPHP / ThinkCMF 伪静态解决方案
- hdu 5718 Oracle
- linux跟本地文件交互
- Java compiler level does not match the version of the installed Java project facet
- FMI飞马网 | 人工智能/大数据/程序/语言/项目管理/机器学习/Python书籍免费赠书