Android探索之BroadcastReceiver具体使用以及安全性探究
前言:
最近的计划是学习一下iOS的NSNotificationCenter,突然想起来的Android的广播机制,所以还是觉得先对BroadcastReceiver来个全面的总结然后再去学习NSNotificationCenter。
BroadcastReceiver简介:
BroadcastReceiver是Android四大组件之一,广播是一种广泛运用的在应用程序之间传输信息的机制,而BroadcastReceiver 是对发送出来的广播进行过滤接收并响应的一类组件;广播接收者( BroadcastReceiver )用于接收广播 Intent ,广播 Intent 的发送是通过调用 Context.sendBroadcast() 、 Context.sendOrderedBroadcast() 来实现的。通常一个广播 Intent 可以被订阅了此 Intent 的多个广播接收者所接收。
广播的使用场景:
1.同一app内部的同一组件内的消息通信(单个或多个线程之间);
2.同一app内部的不同组件之间的消息通信(单个进程);
3.同一app具有多个进程的不同组件之间的消息通信;
4.不同app之间的组件之间消息通信;
5.Android系统在特定情况下与App之间的消息通信。
广播的分类:
普通广播:
发送方式:Context.sendBroadcast()
优点:完全异步,消息传递效率高,
缺点:不能处理广播传给一个接收者,不能终止广播的传播
有序广播:
发送方式:Context.sendOrderedBroadcast()
优点:可以根据广播接收者的优先级依次传播,广播接收者可以处理广播然后再传给一下广播接收者,也可以根据需要调用abortBroadcast()终止广播传播。
缺点:效率低
广播的使用方式:
动态注册:
//注册广播
private void registerReceiver(){
IntentFilter dynamicFilter = new IntentFilter();
dynamicFilter.addAction(ActionCodes.DYNAMICACTION);//添加动态广博Action
registerReceiver(dynamicReceiver, dynamicFilter);
} //解除注册
private void unRegisterReceiver()
{
unregisterReceiver(dynamicReceiver);
} //动态广播的Receiver
private BroadcastReceiver dynamicReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) { if(intent.getAction().equals(ActionCodes.DYNAMICACTION)){ //动作检测
String msg = intent.getStringExtra("msg");
String finalMsg= String.format("%s%s","CActivity----->收到广播:",msg);
Log.e("dynamicReceiver",finalMsg);
Toast.makeText(context, finalMsg, Toast.LENGTH_SHORT).show();
}
}
};
一般情况在Activity/Fragment 的onCreate/onStart/onResume 中注册, 在onDestory/onStop/onPause 中解除注册,根据不同的需求选择不能的生命周期函数。
静态注册:
<receiver
android:name=".StaticReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100">
<action android:name="com.whoislcj.broadcastreceiver.staticreceiver" />
</intent-filter>
</receiver>
发送广播:
//发送普通广播
Intent intent = new Intent();
intent.setAction(ActionCodes.DYNAMICACTION);//设置Action
intent.putExtra("msg", "我是普通广播(动态注册)");//添加附加信息
sendBroadcast(intent); //发送有序广播
Intent intent = new Intent();
intent.setAction(ActionCodes.DYNAMICACTION);//设置Action
intent.setPackage(getPackageName());//设置包名
intent.putExtra("msg", "我是有序广播(动态注册)");//添加附加信息
sendOrderedBroadcast(intent,null);
以上基本上可以满足广播的基本使用了,接下来我们在写个测试程序:分别在A,B,C三个Activity中动态注册广播,分别发送普通广播和和有序广播。
发送普通广播接收顺序:

分别给A,B,C三个Activity中动态注册广播的优先级设置未100,500,1000接收顺序:

附上设置优先级方式:
IntentFilter dynamicFilter = new IntentFilter();
dynamicFilter.addAction(ActionCodes.DYNAMICACTION);//添加动态广播的Action
dynamicFilter.setPriority(1000);//设置优先级
registerReceiver(dynamicReceiver, dynamicFilter);
上文已知有序广播可以修改广播信息传递给下一级优先级低的接收者,我们让BActivity修改 让AActivity接收:
BActivity 广播实现
//动态广播的Receiver
private BroadcastReceiver dynamicReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(ActionCodes.DYNAMICACTION)){ //动作检测
String msg = intent.getStringExtra("msg");
String finalMsg= String.format("%s%s","BActivity----->收到广播:",msg);
Log.e("dynamicReceiver",finalMsg);
Toast.makeText(context, finalMsg, Toast.LENGTH_SHORT).show(); if(isOrderedBroadcast()) {
//创建一个Bundle对象,并存入数据
Bundle bundle = new Bundle();
bundle.putString("msg", msg + "来自BActivity");
//将bundle放入结果中
setResultExtras(bundle);
//取消Broadcast的继续发送
//abortBroadcast();
}
}
}
};
AActivity 如何接收:
//动态广播的Receiver
private BroadcastReceiver dynamicReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(ActionCodes.DYNAMICACTION)) { //动作检测 String msg = intent.getStringExtra("msg");
String finalMsg = String.format("%s%s", "AActivity----->收到广播:", msg);
Log.e("dynamicReceiver", finalMsg);
if (isOrderedBroadcast()) {
Bundle bundle = getResultExtras(true);//接收来自上一级优先级较高的广播修改的信息
String from = bundle.getString("msg");
if (TextUtils.isEmpty(from)) {
return;
}
Log.e("dynamicReceiver", String.format("%s%s", "AActivity----->收到广播:", from));
Toast.makeText(context, finalMsg, Toast.LENGTH_SHORT).show();
}
}
}
};
运行结果:

有序广播如何终止广播传播:
// 终止Broadcast的继续发送
abortBroadcast();
运行结果:

静态注册的广播上述测试运行结果一致,设置优先级方式不同而已:
<receiver
android:name=".AStaticReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100"><!--设置优先级-->
<action android:name="com.whoislcj.broadcastreceiver.staticreceiver" />
</intent-filter>
</receiver>
接下来测试一下app应用之间发送广播,发送方式也是通过隐式Intent方式:
动态注册广播接收情况:
普通广播:

有序广播:

静态注册广播接收情况:
普通广播:

有序广播:

看了上述测试结果基本上和app内运行效果一模一样,所以按照上述那种注册方式和使用方式,一旦app被反编译之后有一定的安全隐患,如何安全的传输呢?
第一种方式:
静态注册广播可以设置:android:exported="false"
<receiver
android:name=".AStaticReceiver"
android:enabled="true"
android:exported="false" <!--设置只能接收app内广播 -->
>
<intent-filter android:priority="100"><!--设置优先级-->
<action android:name="com.whoislcj.broadcastreceiver.staticreceiver" />
</intent-filter>
</receiver>
第二种方式:通过设置发送的广播只能app内接收
Intent intent = new Intent();
intent.setAction(ActionCodes.DYNAMICACTION);//设置Action
intent.setPackage(getPackageName());//设置包名使广播只能被包名的app内接收者接收
intent.putExtra("msg", "我是普通广播(动态注册)");//添加附加信息
sendBroadcast(intent);
第三种方式通过自定义权限:通过上述两种方式只能达到屏蔽外来广播以及广播只在app内传播,无法实现app之间安全发送广播
自定义权限:
<permission android:name="com.whoislcj.broadcastreceiver.MySelfBroadcastReceiver" />
<uses-permission android:name="com.whoislcj.broadcastreceiver.MySelfBroadcastReceiver"/>
动态注册:
IntentFilter dynamicFilter = new IntentFilter();
dynamicFilter.addAction(ActionCodes.DYNAMICACTION);//添加动态广播的Action
dynamicFilter.setPriority(500);
//设置权限
registerReceiver(dynamicReceiver, dynamicFilter,ActionCodes.MYPERMISSION,null);
静态注册:
<receiver
android:name=".BStaticReceiver"
android:enabled="true"
android:exported="true"
<!--设置权限-->
android:permission="com.whoislcj.broadcastreceiver.MySelfBroadcastReceiver">
<intent-filter android:priority="500">
<action android:name="com.whoislcj.broadcastreceiver.staticreceiver" />
</intent-filter>
</receiver>
发送广播:
//普通广播
sendBroadcast(intent,ActionCodes.MYPERMISSION); //有序广播
sendOrderedBroadcast(intent,ActionCodes.MYPERMISSION);
第四种方式:通过LocalBroadcastManager方式
注册:
LocalBroadcastManager.getInstance(getInstance()).registerReceiver(receiver, filter);
解除注册:
LocalBroadcastManager.getInstance(getInstance()).unregisterReceiver(receiver);
发送广播:
LocalBroadcastManager.getInstance(getInstance()).sendBroadcastSync(intent);
总结:
通过本文可以看出BroadcastReceiver使用方式虽然看似简单,想要实现比较完善的广播还是要费一番功夫的。
Android探索之BroadcastReceiver具体使用以及安全性探究的更多相关文章
- Android View各种尺寸位置相关的方法探究
Android View各种尺寸位置相关的方法探究 本来想做一个View间的碰撞检测之类的. 动手做了才发现不是想象的那么简单. 首先,写好了碰撞检测的工具类如下: package com.mengd ...
- Android LocalBroadcastManager 与 BroadcastReceiver
Android中BroadcastReceiver主要用途有 发送通知,更新UI或者数据,应用程序间相互通信,监听系统状态(比如开机,网络等) Android中发送广播的方式: 普通广播:无论优先级大 ...
- Android探索之旅 | AIDL原理和实例讲解
轉載自http://www.jianshu.com/p/ef86f682a8f9 -- 作者 谢恩铭 转载请注明出处 前言 为使应用程序之间能够彼此通信,Android提供了IPC (Inter Pr ...
- Android探索之AIDL实现进程间通信
前言: 前面总结了程序间共享数据,可以使用ContentProvider也可以使用SharedPreference,那么进程间怎么共享内存呢?Android系统中的进程之间不能共享内存,因此,需要提供 ...
- Android - 广播接收者 - BroadcastReceiver
BroadcastReceiver 介绍: 广播是一种广泛运用的在应用程序之间传输信息的机制 .而 BroadcastReceiver 是对发送出来的广播 进行过滤接收并响应的一类组件 接受一种或者多 ...
- android广播接收器BroadcastReceiver
首先看一下什么是 BroadcastReceiver BroadcastReceiver:直译是"广播接收者",所以它的作用是用来接收发送过来的广播的. 那我们有必要知道:什么是广 ...
- Android 学习笔记 BroadcastReceiver广播...
PS:不断提升自己,是件好事... 学习内容: 1.BroadcastReceiver的使用.. 2.通过BroadcastReceiver去启动Service... 1.BroadcastRecei ...
- Android 利用Service BroadcastReceiver实现小例子
Activity: package com.example.test; import android.app.Activity; import android.content.Context; imp ...
- Android开发之BroadcastReceiver
BroadcastReceiver:广播接收者.用来接收系统或应用中的广播. 在Android系统中,广播体现在方方面面,例如当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的功能: ...
随机推荐
- Linux下uniq命令的详解
-c 在输出行前面加上每行在输入文件中出现的次数. -d 仅显示重复行. -u 仅显示不重复的行. 示例 1.去重,有多行一样的只显示一行cat 4.txt |sort - ...
- js中函数的一些理论知识
函数的一些理论知识 1. 函数: 执行一个明确的动作并提供一个返回值的独立代码块.同时函数也是javascript中的一级公民(就是函数和其它变量一样). 2.函数的 ...
- iOS Block理解
以前看到Block觉得也没什么,不就是类似函数的东西,这东西在C#里就是委托,在Java里就是块,有什么稀奇的.但看到一点进阶的内容后,发现这个东西确实有用. 所以做下总结. 一.块的基本用法 块的语 ...
- linux下Vim的使用
在vim中移动光标跟其他的编辑器中有很大的区别,不过一旦学会了,就会飞速的在文本中移动 复制粘贴dd 删除光标所在行dw 删除一个字(word)x 删除当前字符X 删除前一个字符D 删除到行末yy 复 ...
- 快速定位性能瓶颈,检查出所有资源(CPU、内存、磁盘IO等)的利用率(utilization)、饱和度(saturation)和错误(error)度量,即USE方法
命令:uptime说明:查看机器分别在1分钟.5分钟.15分钟的平均负载情况,显示的数字表示等待cpu资源的进程和阻塞在不可中断io进程的数量,如果1分钟的平均负载很高,而15分钟的平均负载很低,说明 ...
- GPRS 接入外网的过程
请问GPRS模块与Internet上主机的连接.数据传输过程 虽然按照GPRS模块的说明文档能够通过内嵌TCP/IP实现数据的传输,但是对GPRS模块和主机之间的连接关系了解得不是很多.有谁可以介绍一 ...
- 循序渐进做项目系列(4)迷你QQ篇(2)——视频聊天!(附源码)
一·效果展示 源码派送:MiniQQ1.1 文字聊天的实现参见:循序渐进做项目系列(3):迷你QQ篇(1)——实现客户端互相聊天 二·服务端设计 对于实现视频聊天而言,服务端最核心的工作就是要构造多媒 ...
- 【腾讯优测干货分享】Android 相机预览方向及其适配探索
本文来自于腾讯bugly开发者社区,未经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/583ba1df25d735cd2797004d 由于Android系统的开放策略 ...
- 递归算法经典实例小结(C#实现)
一 .递归算法简介 在数学与计算机科学中,递归是指在函数的定义中使用函数自身的方法. 递归算法是一种直接或者间接地调用自身算法的过程.在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往 ...
- [译]Asp.net MVC 之 Contorllers(二)
URL路由模块 取代URL重写 路由请求 URL路由模块的内部结构 应用程序路由 URL模式和路由 定义应用程序路由 处理路由 路由处理程序 处理物理文件请求 防止路由定义的URL 属性路由 书接上回 ...