Android四大组件---BroadcastReceiver
前言:
BroadcastReceiver
(广播接收器),属于Android
四大组件之一- 在
Android
开发中,BroadcastReceiver
的应用场景非常多 - 今天,我将详细讲解关于
BroadcastReceiver
的一切相关知识
目录:
下面小可会把自己使用广播的心得体会以及广播dev具体用途详细的讲解。
1:定义
广播,是一个全局的监听器,属于Android
四大组件之一,Android
广播分为两个角色:广播发送者、广播接收者。
2:作用
监听 / 接收 应用 App
发出的广播消息,并 做出响应。
3:应用场景
Android
不同组件间的通信(含 :应用内 / 不同应用之间)- 多线程通信
- 与
Android
系统在特定情况下的通信
比如:电话呼入时、网络可用时,电池电量过低预警。。。
4:实现原理
4.1 采用的模型
Android
中的广播使用了设计模式中的观察者模式:基于消息的发布 / 订阅事件模型- Android将广播的发送者 和 接收者 解耦,使得系统方便集成,更易扩展,(体现编程思想的解耦)
4.2 模型讲解
模型中有3个角色
- 消息订阅者(广播接收者)
- 消息发布者(广播发布者)
- 消息中心(
AMS
,即Activity Manager Service
)
示意图如下
5:使用流程
好了,下面我将一步步介绍如何使用BroadcastReceiver,
即上图中的 开发者手动完成部分
5.1 自定义广播接收者BroadcastReceiver
- 继承
BroadcastReceivre
基类 - 必须复写抽象方法
onReceive()
方法
注意事项
- 广播接收器接收到相应广播后,会自动回调
onReceive()
方法 - 一般情况下,
onReceive
方法会涉及 与 其他组件之间的交互,如发送Notification
、启动Service
等 - 默认情况下,广播接收器运行在
UI
线程,因此,onReceive()
方法不能执行耗时操作,否则将导致ANR
话不多说,直接code,代码范例
mBroadcastReceiver.java
// 继承BroadcastReceivre基类
public class mBroadcastReceiver extends BroadcastReceiver {// 复写onReceive()方法// 接收到广播后,则自动调用该方法@Overridepublic void onReceive(Context context, Intent intent) {//写入接收广播后的操作}
}
5.2 广播接收器注册
注册的方式分为两种:
- 静态注册
- 动态注册
5.2.1 静态注册
- 注册方式:在AndroidManifest.xml里通过<receive>标签声明
- 属性说明:
<receiver android:enabled=["true" | "false"]
//此broadcastReceiver能否接收其他App的发出的广播
//默认值是由receiver中有无intent-filter决定的:如果有intent-filter,默认值为true,否则为falseandroid:exported=["true" | "false"]android:icon="drawable resource"android:label="string resource"
//继承BroadcastReceiver子类的类名android:name=".mBroadcastReceiver"
//具有相应权限的广播发送者发送的广播才能被此BroadcastReceiver所接收;android:permission="string"
//BroadcastReceiver运行所处的进程
//默认为app的进程,可以指定独立的进程
//注:Android四大基本组件都可以通过此属性指定自己的独立进程android:process="string" >//用于指定此广播接收器将接收的广播类型
//本示例中给出的是用于接收网络状态改变时发出的广播<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" /></intent-filter>
</receiver>
- 注册示例
<receiver //此广播接收者类是mBroadcastReceiverandroid:name=".mBroadcastReceiver" >//用于接收网络状态改变时发出的广播<intent-filter><action android:name="android.net.conn.CONNECTIVITY_CHANGE" /></intent-filter>
</receiver>
当此 App
首次启动时,系统会自动实例化mBroadcastReceiver
类,并注册到系统中。
5.2.2 动态注册
- 注册方式:在代码中调用
Context.registerReceiver()
方法 - 具体代码如下
// 选择在Activity生命周期方法中的onResume()中注册
@Overrideprotected void onResume(){super.onResume();// 1. 实例化BroadcastReceiver子类 & IntentFiltermBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();IntentFilter intentFilter = new IntentFilter();// 2. 设置接收广播的类型intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);// 3. 动态注册:调用Context的registerReceiver()方法registerReceiver(mBroadcastReceiver, intentFilter);}// 注册广播后,要在相应位置记得销毁广播
// 即在onPause() 中unregisterReceiver(mBroadcastReceiver)
// 当此Activity实例化时,会动态将MyBroadcastReceiver注册到系统中
// 当此Activity销毁时,动态注册的MyBroadcastReceiver将不再接收到相应的广播。@Overrideprotected void onPause() {super.onPause();//销毁在onResume()方法中的广播unregisterReceiver(mBroadcastReceiver);}
}
特别注意
- 动态广播最好在
Activity
的onResume()
注册、onPause()
注销。 - 原因:
- 对于动态广播,有注册就必然得有注销,否则会导致内存泄露
- 重复注册、重复注销也不允许
Activity
生命周期如下:
Activity生命周期的方法是成对出现的:
- onCreate() & onDestory()
- onStart() & onStop()
- onResume() & onPause()
在onResume()注册、onPause()注销是因为onPause()在App死亡前一定会被执行,从而保证广播在App死亡前一定会被注销,从而防止内存泄露。
1:不在onCreate() & onDestory() 或 onStart() & onStop()注册、注销是因为:
当系统因为内存不足(优先级更高的应用需要内存,请看上图红框)要回收Activity占用的资源时,Activity在执行完onPause()方法后就会被销毁,有些生命周期方法onStop(),onDestory()就不会执行。当再回到此Activity时,是从onCreate方法开始执行。2:假设我们将广播的注销放在onStop(),onDestory()方法里的话,有可能在Activity被销毁后还未执行onStop(),onDestory()方法,即广播仍还未注销,从而导致内存泄露。3:但是,onPause()一定会被执行,从而保证了广播在App死亡前一定会被注销,从而防止内存泄露。
5.2.3 两种注册方式的区别
5.3 广播发送者向AMS发送广播
5.3.1 广播的发送
- 广播 是 用”意图(
Intent
)“标识 - 定义广播的本质 = 定义广播所具备的“意图(
Intent
)” - 广播发送 = 广播发送者 将此广播的“意图(
Intent
)”通过sendBroadcast()方法发送出去
5.3.2 广播的类型
广播的类型主要分为5类:
- 普通广播(
Normal Broadcast
) - 系统广播(
System Broadcast
) - 有序广播(
Ordered Broadcast
) - 粘性广播(
Sticky Broadcast
) - App应用内广播(
Local Broadcast
)
具体说明如下:
1. 普通广播(Normal Broadcast)
即 开发者自身定义 intent
的广播(最常用)。发送广播使用如下:
Intent intent = new Intent();
//对应BroadcastReceiver中intentFilter的action
intent.setAction(BROADCAST_ACTION);
//发送广播
sendBroadcast(intent);
- 若被注册了的广播接收者中注册时
intentFilter
的action
与上述匹配,则会接收此广播(即进行回调onReceive()
)。如下mBroadcastReceiver
则会接收上述广播
<receiver //此广播接收者类是mBroadcastReceiverandroid:name=".mBroadcastReceiver" >//用于接收网络状态改变时发出的广播<intent-filter><action android:name="BROADCAST_ACTION" /></intent-filter>
</receiver>
- 若发送广播有相应权限,那么广播接收者也需要相应权限
2. 系统广播(System Broadcast)
- Android中内置了多个系统广播:只要涉及到手机的基本操作(如开机、网络状态变化、拍照等等),都会发出相应的广播
- 每个广播都有特定的Intent - Filter(包括具体的action),Android系统广播action如下:
系统操作 | action |
---|---|
监听网络变化 | android.net.conn.CONNECTIVITY_CHANGE |
关闭或打开飞行模式 | Intent.ACTION_AIRPLANE_MODE_CHANGED |
充电时或电量发生变化 | Intent.ACTION_BATTERY_CHANGED |
电池电量低 | Intent.ACTION_BATTERY_LOW |
电池电量充足(即从电量低变化到饱满时会发出广播 | Intent.ACTION_BATTERY_OKAY |
系统启动完成后(仅广播一次) | Intent.ACTION_BOOT_COMPLETED |
按下照相时的拍照按键(硬件按键)时 | Intent.ACTION_CAMERA_BUTTON |
屏幕锁屏 | Intent.ACTION_CLOSE_SYSTEM_DIALOGS |
设备当前设置被改变时(界面语言、设备方向等) | Intent.ACTION_CONFIGURATION_CHANGED |
插入耳机时 | Intent.ACTION_HEADSET_PLUG |
未正确移除SD卡但已取出来时(正确移除方法:设置--SD卡和设备内存--卸载SD卡) | Intent.ACTION_MEDIA_BAD_REMOVAL |
插入外部储存装置(如SD卡) | Intent.ACTION_MEDIA_CHECKING |
成功安装APK | Intent.ACTION_PACKAGE_ADDED |
成功删除APK | Intent.ACTION_PACKAGE_REMOVED |
重启设备 | Intent.ACTION_REBOOT |
屏幕被关闭 | Intent.ACTION_SCREEN_OFF |
屏幕被打开 | Intent.ACTION_SCREEN_ON |
关闭系统时 | Intent.ACTION_SHUTDOWN |
重启设备 | Intent.ACTION_REBOOT |
注意:当使用系统广播时,只需要在注册广播接收者时定义相关的action即可,并不需要手动发送广播,当系统有相关操作时会自动进行系统广播
3. 有序广播(Ordered Broadcast)
- 定义
发送出去的广播被广播接收者按照先后顺序接收
有序是针对广播接收者而言的
广播接受者接收广播的顺序规则(同时面向静态和动态注册的广播接受者)
- 按照Priority属性值从大-小排序;
- Priority属性相同者,动态注册的广播优先;
特点
- 接收广播按顺序接收
- 先接收的广播接收者可以对广播进行截断,即后接收的广播接收者不再接收到此广播;
- 先接收的广播接收者可以对广播进行修改,那么后接收的广播接收者将接收到被修改后的广播
具体使用
有序广播的使用过程与普通广播非常类似,差异仅在于广播的发送方式:
sendOrderedBroadcast(intent);
4. App应用内广播(Local Broadcast)
背景
Android中的广播可以跨App直接通信(exported对于有intent-filter情况下默认值为true)冲突
可能出现的问题:- 其他App针对性发出与当前App intent-filter相匹配的广播,由此导致当前App不断接收广播并处理;
- 其他App注册与当前App一致的intent-filter用于接收广播,获取广播具体信息;
即会出现安全性 & 效率性的问题。
解决方案
使用App应用内广播(Local Broadcast)
- App应用内广播可理解为一种局部广播,广播的发送者和接收者都同属于一个App。
- 相比于全局广播(普通广播),App应用内广播优势体现在:安全性高 & 效率高
具体使用1 - 将全局广播设置成局部广播
- 注册广播时将exported属性设置为false,使得非本App内部发出的此广播不被接收;
- 在广播发送和接收时,增设相应权限permission,用于权限验证;
- 发送广播时指定该广播接收器所在的包名,此广播将只会发送到此包中的App内与之相匹配的有效广播接收器中。
通过intent.setPackage(packageName)指定报名
具体使用2 - 使用封装好的LocalBroadcastManager类
使用方式上与全局广播几乎相同,只是注册/取消注册广播接收器和发送广播时将参数的context变成了LocalBroadcastManager的单一实例
注:对于LocalBroadcastManager方式发送的应用内广播,只能通过LocalBroadcastManager动态注册,不能静态注册
//注册应用内广播接收器
//步骤1:实例化BroadcastReceiver子类 & IntentFilter mBroadcastReceiver
mBroadcastReceiver = new mBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter(); //步骤2:实例化LocalBroadcastManager的实例
localBroadcastManager = LocalBroadcastManager.getInstance(this);//步骤3:设置接收广播的类型
intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);//步骤4:调用LocalBroadcastManager单一实例的registerReceiver()方法进行动态注册
localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);//取消注册应用内广播接收器
localBroadcastManager.unregisterReceiver(mBroadcastReceiver);//发送应用内广播
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
localBroadcastManager.sendBroadcast(intent);
5. 粘性广播(Sticky Broadcast)
由于在Android5.0 & API 21中已经失效,所以不建议使用,在这里也不作过多的总结。
6. 特别注意
对于不同注册方式的广播接收器回调OnReceive(Context context,Intent intent)中的context返回值是不一样的:
- 对于静态注册(全局+应用内广播),回调onReceive(context, intent)中的context返回值是:ReceiverRestrictedContext;
- 对于全局广播的动态注册,回调onReceive(context, intent)中的context返回值是:Activity Context;
- 对于应用内广播的动态注册(LocalBroadcastManager方式),回调onReceive(context, intent)中的context返回值是:Application Context。
- 对于应用内广播的动态注册(非LocalBroadcastManager方式),回调onReceive(context, intent)中的context返回值是:Activity Context;
7. 总结
BroadcastReceiver是Android系统四大组件之一,因此学好Android四大组件,是Android开发必备技能,Android做为全球最大的移动端操作系统,霸据这全球百分之九十的手机市场,应用市场及其广阔,尤其是面临5G的到来,物联网技术更是大势所趋,相信搭载着Android终端的设备会逐渐渗透到我们的生活的每一个角落,服务全球,带人类进入更好更便捷的新纪元。
在接下来的几天内,我会继续讲解Android四大组件的其他三大兄弟,敬请期待,喜欢大家可以共同进步成长。
Android四大组件---BroadcastReceiver相关推荐
- Android 四大组件 -- BroadcastReceiver(广播)
Android开发的四大组件分别是: 活动(activity),用于表现功能; 服务(service),后台运行服务,不提供界面呈现: 广播接受者(BroadcastReceive),勇于接收广播: ...
- Android四大组件-Service
目录 启动方式 独立启动 使用场景 生命周期 绑定启动 使用场景 生命周期 特性 多次启动 版本适配 5.0(21) 8.0(26) 9.0(28) 12(31) 后台启动服务思路 广播启动 省电白名 ...
- Android四大组件之BroadCastReceiver
1. 基本概念 在Android 中,Broadcast 是一种广泛运用的在应用程序之间传输信息的机制.而BroadcastReceiver 是对发送出来的Broadcast 进行过滤接受并响应的一类 ...
- android 广播的权限,Android四大组件详解之BroadcastReceiver广播接收者
Android四大组件详解---BroadcastReceicer广播接收者 广播有两个角色,一个是广播发送者,另一个是广播接收者. 广播按照类型分为两种,一种是全局广播,另一种是本地广播 全局广播: ...
- Android 四大组件之——Acitivity(一)
一,什么是Activity activity是Android组件中最基本也是最为常见用的四大组件之一.Android四大组件有Activity,Service服务,Content Provider内容 ...
- android四大组件的作用简书,Android四大组件是什么
Android四大组件是:活动.服务.广播接收器.内容提供商.它们的英文名称是ACTIVITY.SERVICE.BroadcastReceiver.Content Provider.四个组件分别起到不 ...
- android四大组件小整
原文来自http://www.jianshu.com/p/478a34af17df 所谓的android四大组件一次是Activity.Service.BroadcastReceiver和Conten ...
- Android 四大组件通信核心
前言 系列文章: Android Activity创建到View的显示过程 Android 四大组件通信核心 Android 系统启动到App 界面完全展示终于明白(图文版) 我们知道Android ...
- Kotlin第七章: Android四大组件
1. 四大组件 四大组件是每一个Android人必须要会,要掌握的知识点,因为他们是我们在日常开发工作中打交道最频繁的组件,而且他们四个在不同的领域扮演着极其重要的角色. Activity: 负责用户 ...
最新文章
- python 元组和列表区别_Python 基础(六):列表与元组
- 基于matlab水轮机期刊,基于MATLAB/SIMULINK的水轮机调节系统寻优
- css border 虚线间距_【前端冷知识】CSS如何实现虚线框动画
- 轻松为Windows系统快速配置多个网关
- 安装adobe acrobat导致回滚
- typescript get方法_使用 Typescript 构建类型安全的 Websocket 应用
- 利用windows 2003 实现×××服务器的组建与架构(一) 移动用户到站点之间的×××...
- 有效使用Eclipse的热门提示
- OpenPBS 脚本
- 最优化学习笔记(十)——对偶线性规划
- 【浏览器】浏览器模式与文档模式区别
- php放量文档,成交量放量过顶买入法(图解)
- mysql优于oracle的地方_MYSQL转为ORACLE要注意的地方
- 综合云平台 - 架构 - 01
- centos 中如何将python更新到最新的版本
- python vim插件_有哪些好用到爆的vim插件?
- python调用鼠标驱动_python_selenium_鼠标操作
- 黑马程序员—黑马历程--我的人生,我的路--黑九的我毕业了
- 开发人员都需要知道的几款优秀数据库管理工具
- 阿里P6+面试:介绍下观察者模式?
热门文章
- TensorFlow 三岁了,你想对它说点什么?
- 给安利公司董事长郑李锦芬女士的一封信
- springboot 整合redis_springboot自动装配原理详解
- 不叫K50 Pro+!Redmi K50系列超大杯或有新名称
- 苹果“噩梦”来袭!iPhone 13、iPad竟遭遇停产 十多年来首次
- 酷派COOL 20 Pro影像大升级:搭载5000万AI三摄 主攻夜景
- 一加9R国行版即将到来:搭载骁龙870 售价预计3K内
- 上市前夕再陷版权纠纷,快手面临的风险却不止于此
- 抖音发布2020数据报告:日均视频搜索量破4亿,70后最爱发表情包
- 华为Mate 40系列预热海报颠覆传闻:这个设计手机圈独树一帜