Android的BroadcastReceiver组件
BroadcastReceiver的作用:
BroadcastReceiver,是和Intent有很大关系的Android组件。
Android中的 Intent 可以用来:
1. 在应用程序内部和应用程序之间传递数据(传输信息的机制),以及通过监听Intent来检测到系统状态的变化;
2. 启动Activity和Service;
3. Broadcast Intent用来在系统范围内公布应用程序事件。
Broadcast Intent用于在系统范围内广播应用程序事件,而BroadcastReceiver则用于接收或监听Intent事件,对发出的Broadcast进行过滤、接受并响应的一类组件(发送通知,更新UI或者数据,应用程序间相互通信,监听系统状态;比如开机,网络等)。上述两者的作用,恰好是相反的。
在Android系统中,广播体现在方方面面,例如当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的功能;当网络状态改变时系统会产生一条广播,接收到这条广播就能及时地做出提示和保存数据等操作;当电池电量改变时,系统会产生一条广播,接收到这条广播就能在电量低时告知用户及时保存进度,等等。
BroadcastReceiver包括两个概念,广播发送者和广播接收者(Receiver),这里的广播实际就是指Intent;应用程序可以自己发送广播自己接收,也可以接受系统或其他应用的广播或是发送广播给其他应用程序。当发送者发送某个广播时,系统会将发送的广播(Intent)与系统中所有注册的符合条件的接收者(Receiver) 的IntentFilter进行匹配。若匹配成功,则执行相应接收者的onReceive(),匹配规则见Intent和IntentFilter的匹配规则。
“Android中的广播机制设计的非常出色,很多事情原本需要开发者亲自操作的,现在只需等待广播告知自己就可以了,大大减少了开发的工作量和开发周期。”
BroadcastReceiver的使用方法:
要使用Broadcast Receiver能够接收广播,就需要对其进行注册,既可以使用代码,也可以在应用程序的manifest文件中注册(此时称为manifest接收器)。无论怎么注册,都需要使用一个Intent Filter来指定要监听哪些Intent(特指:Intent的Action)和数据。
对于包含manifest接收器的应用程序,在Intent被广播出去的时候,应用程序不一定非要处于运行状态才能执行接收(而对于在代码中注册的接收器只会在包含它的应用程序组件运行时才会响应Broadcast Intent)。当匹配的Intent被广播出去的时候,它们会被自动地启动。
对于资源管理来说,这一点是非常优秀的,因为它提供了一种能够创建出事件驱动型的应用程序机制(不仅可以接受应用程序自定义的广播,还可以接受系统级别的广播)。即使应用程序被关闭或者销毁了,也仍然能够对广播事件作出响应。
1. 静态注册广播接受者
public class DemoBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String msg = intent.getStringExtra("msg");
Log.d(Constanst.TAG, "DemoBroadcastReceiver::"+msg);
}
}
对应的要到AndroidManifest.xml文件中进行注册:
<receiver android:name=".DemoBroadcastReceiver">
<intent-filter>
<action android:name="com.androidiot.demo.DEMO.TEST"></action>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</receiver>
2. 动态注册广播
@Override
protected void onStart() {
super.onStart(); // TODO 此处注册广播监听
receiver = new MyBroadReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(Constanst.ACTION);
MainActivity.this.registerReceiver(receiver, filter);
}
此处是在Activity中的onStart()中注册广播,与此对应的,需要在onPause()中取消广播监听:
@Override
protected void onPause() {
super.onPause();
// TODO 此处取消广播监听
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
}
对于自己发送和接受的广播可以通过registerReceiver注册,对于系统常用广播的接收通常用<receiver>标签注册。registerReceiver可以手动控制,所以适当的注册和取消注册能节省系统资源,<receiver>标签系统开机后一直有效。
BroadcastReceiver在onReceive()执行结束后即表示生命周期结束,所以不适合在onReceive中做绑定服务操作;结束后若某个进程只含有该BroadcastReceiver,则优先级将降低可能被系统回收,所以BroadcastReceiver中不适合做一些异步操作,如新建线程下载数据,BroadcastReceiver结束后可能在异步操作完成前进程已经被系统kill。同时由于ANR限制BroadcastReceiver的onReceive()必须在5秒内完成,而且onReceive()默认会在主线程中执行,所以BroadcastReceiver中不适合做一些耗时操作,对于耗时操作需要交给service处理,比如网络或数据库耗时操作、对话框的显示(因为现实时间可能超时,用Notification代替)。
BroadcastReceiver的类型:
Android中的广播类型分为两种:无序广播和有序广播;前者为异步的,也就是大致实现了同一时间接收到广播,不分先后顺序;后者根据接受者的优先级别,实现广播的先后接受。
无序广播的各个接受者,无法做到停止广播的传递;有序广播中,优先接收到广播的接受者可以实现终止广播的传递(并且可以改变传递的Extras的内容)。
BroadcastReceiver的使用注意事项:
对于接收到指定广播的onReceive(),必须在5s内执行完毕;否则会出现ANR。
一般情况下,Broadcast Receiver将会更新内容、启动Servicee、更新UI,或者使用Notification Manager来通知用户。5秒的执行限制保证了主要的处理工作不能够、也不应该由Broadcast Receiver直接完成。
BroadcastReceiver的设计初衷就是从全局考虑的,可以方便应用程序和系统、应用程序之间、应用程序内的通信,所以对单个应用程序而言BroadcastReceiver是存在安全性问题的,相应问题及解决如下:
a、当应用程序发送某个广播时系统会将发送的Intent与系统中所有注册的BroadcastReceiver的IntentFilter进行匹配,若匹配成功则执行相应的onReceive函数。可以通过类似sendBroadcast(Intent, String)的接口在发送广播时指定接收者必须具备的permission。或通过Intent.setPackage设置广播仅对某个程序有效。
b. 当应用程序注册了某个广播时,即便设置了IntentFilter还是会接收到来自其他应用程序的广播进行匹配判断。对于动态注册的广播可以通过类似registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler)的接口指定发送者必须具备的permission,对于静态注册的广播可以通过android:exported="false"属性表示接收者对外部应用程序不可用,即不接受来自外部的广播。
c.上面两个问题其实都可以通过LocalBroadcastManager来解决,LocalBroadcastManager只会将广播限定在当前应用程序中。LocalBroadcastManager局部广播管理器,包含在Android Support Library中,局部广播的作用域要小,使用局部广播管理器比发送全局广播更加有效,也确保了应用程序外部的任何组件都收不到广播的Intent,不会有私人数据或敏感数据泄露出去。类似的,其他的应用程序也不能向你的接收器发送广播,避免了这些接收器成为安全漏洞。
Android的BroadcastReceiver组件的更多相关文章
- Android中BroadcastReceiver组件具体解释
Android系统的4个组件最终还剩一种组件了BroadcastReceiver,这个组件是全局监听器,能够监听系统全局的广播消息,能够方便的实现系统中不同组件之间的通信 BroadcastRecei ...
- Android学习(十三) BroadcastReceiver组件(广播)
一.Broadcast(广播) 是一种广泛应用在应用程序之间传输信息的机制. 二.Broadcast(广播接收器) 是对发送出来的广播进行过滤接收并响应的一类组件,它就是用来接收来自系统和应用中的广播 ...
- android BroadcastReceiver组件简单的使用
1.清单文件 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android=& ...
- Android中BroadcastReceiver的两种注册方式(静态和动态)详解
今天我们一起来探讨下安卓中BroadcastReceiver组件以及详细分析下它的两种注册方式. BroadcastReceiver也就是"广播接收者"的意思,顾名思义,它就是用来 ...
- Android消息传递之组件间传递消息
前言: 上篇学习总结了Android通过Handler消息机制实现了工作线程与UI线程之间的通信,今天来学习一下如何实现组件之间的通信.本文依然是为学习EventBus做铺垫,有对比才能进步,今天主要 ...
- Android的四大组件之Activity
Android的四大组件之Activity Activity:是Android组件中最基本也是最为常见用的四大组件(Activity,Service服务,Content Provider内容提供者,B ...
- Android 广播 BroadcastReceiver
Android 系统里定义了各种各样的广播,如电池的使用状态,电话的接收和短信的接收,开机启动都会产生一个广播.当然用户也可以自定义自己的广播. 既然说到广播,那么必定有一个广播发送者,以及广播接收器 ...
- Android四大基本组件介绍与生命周期
Android四大基本组件介绍与生命周期 Android四大基本组件分别是Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器 ...
- Android中BroadcastReceiver广播
BroadCastReceiver 简介 广播接收者( BroadcastReceiver )用于接收广播 Intent ,广播 Intent 的发送是通过调用 Context.sendBroadca ...
随机推荐
- Python爬虫之二
1)什么叫做URL url是统一资源定位符,对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址.互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及 ...
- JN_0006:MongoDB未授权访问漏洞处理
开启MongoDB服务时不添加任何参数时,默认是没有权限验证的,登录的用户可以通过默认端口无需密码对数据库任意操作而且可以远程访问数据库. 2.[修复建议]:临时方案:配置AUTH,做好访问认证.打开 ...
- javascript节点移除
var itemdel = document.getElementById("test"); itemdel.removeChild(lis[0]); 兼容性较好 itemdel. ...
- tex 进度条
\documentclass{beamer} \usepackage{tikz} \usetikzlibrary{calc} \definecolor{pbblue}{HTML}{0A75A8}% f ...
- [物理学与PDEs]第5章第5节 弹性动力学方程组及其数学结构
5.5.1 线性弹性动力学方程组 1. 线性弹性动力学方程组 $$\beex \bea 0&=\rho_0\cfrac{\p{\bf v}}{\p t}-\Div_x{\bf P}-\r ...
- [物理学与PDEs]第1章第7节 媒质中的 Maxwell 方程组 7.2 媒质交界面上的条件
通过 Maxwell 方程组的积分形式易在交界面上各量应满足交界面条件: $$\beex \bea \sez{{\bf D}}\cdot{\bf n}=\omega_f,&\sex{\omeg ...
- springMVC入门思路整理
- 移动端bug集合
移动端软键盘遮挡输入框&IOS移动端点击输入框字体放大&IOS点击闪烁 移动端软键盘遮挡输入框 ——> 转载自: https://www.jb51.net/article/1 ...
- centos 搭建 leanote
centos 搭建leanote(蚂蚁笔记) 至于蚂蚁笔记是什么可以看官网的介绍,https://leanote.com/ ,我只能说 nice,你值得拥有. 开始搭建(源码安装,安装路径在 /et ...
- Solidity属性和方法的访问权限
属性:默认是internal的类型,外部是不可以访问调用的,如果加上public的话,那么是会自动为这个属性加上一个get的方法的,比如uint public _age; => functi ...