Android 中的BroadCastReceiver
BroadCastReceiver 简介 (末尾有源码)
BroadCastReceiver 源码位于: framework/base/core/java/android.content.BroadcastReceiver.java
广播接收者( BroadcastReceiver )用于接收广播 Intent ,广播 Intent 的发送是通过调用 Context.sendBroadcast() 、 Context.sendOrderedBroadcast() 来实现的。通常一个广播 Intent 可以被订阅了此 Intent 的多个广播接收者所接收。
广播是一种广泛运用的在应用程序之间传输信息的机制 。而 BroadcastReceiver 是对发送出来的广播进行过滤接收并响应的一类组件;
来自普通应用程序,如一个应用程序通知其他应用程序某些数据已经下载完毕。
BroadcastReceiver 自身并不实现图形用户界面,但是当它收到某个通知后, BroadcastReceiver 可以启动 Activity 作为响应,或者通过 NotificationMananger 提醒用户,或者启动 Service 等等。
BroadCastReceiver 的机制
1. 机制
在 Android 里面有各种各样的广播,比如电池的使用状态,电话的接收和短信的接收都会产生一个广播,应用程序开发者也可以监听这些广播并做出程序逻辑的处理。如图:
2. 实现
用接收短信举例:
第一种方式 :
实现
public class MyBroadcastReceiver extends BroadcastReceiver {
// action 名称
String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED" ;
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals( SMS_RECEIVED )) {
// 相关处理 : 地域变换、电量不足、来电来信;
}
}
}
系统注册:在 AndroidManifest.xml 中注册
< receiver android:name = ".MyBroadcastReceiver" >
< intent-filter android:priority = "1000" >
< action android:name = " android.provider.Telephony.SMS_RECEIVED" />
</ intent-filter >
</ receiver > 当然了需要权限 :
< uses-permission android:name = "android.permission.RECEIVE_SMS" />
< uses-permission android:name = "android.permission.SEND_SMS" />
第二种方式:
// 广播接收者 - 广播的接收
private BroadcastReceiver myBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 相关处理,如收短信,监听电量变化信息
}
};
代码中注册:
IntentFilter intentFilter = new IntentFilter( "android.provider.Telephony.SMS_RECEIVED " );
registerReceiver( mBatteryInfoReceiver , intentFilter);
3. 生命周期
描述了 Android 中广播的生命周期,其次它并不像 Activity 一样复杂,运行原理很简单如下图:
生命周期只有十秒左右,如果在 onReceive() 内做超过十秒内的事情,就会报错 。
每次广播到来时 , 会重新创建 BroadcastReceiver 对象 , 并且调用 onReceive() 方法 , 执行完以后 , 该对象即被销毁 . 当 onReceive() 方法在 10 秒内没有执行完毕, Android 会认为该程序无响应 . 所以在
BroadcastReceiver 里不能做一些比较耗时的操作 , 否侧会弹出 ANR(Application No
Response) 的对话框 . 。(如图):
怎么用好 BroadcastReceiver ?
如果需要完成一项比较耗时的工作 , 应该通过发送 Intent 给 Service, 由 Service 来完成 . 这里不能使用子线程来解决 , 因为 BroadcastReceiver 的生命周期很短 , 子线程可能还没有结束
BroadcastReceiver 就先结束了 .BroadcastReceiver 一旦结束 , 此时 BroadcastReceiver 的
所在进程很容易在系统需要内存时被优先杀死 , 因为它属于空进程 ( 没有任何活动组件的进程 ). 如果它的宿主进程被杀死 , 那么正在工作的子线程也会被杀死 . 所以采用子线程来解决是不可靠的 .
广播类型及广播的收发
广播类型
普通广播 (Normal broadcasts)
发送一个广播,所以监听该广播的广播接收者都可以监听到改广播。
异步广播 , 当处理完之后的Intent ,依然存在,这时候registerReceiver(BroadcastReceiver, IntentFilter) 还能收到他的值,直到你把它去掉 , 不能将处理结果传给下一个接收者 , 无法终止广播 .
有序广播 (Ordered broadcasts)
按照接收者的优先级顺序接收广播 , 优先级别在 intent-filter 中的 priority 中声明 ,-1000 到
1000 之间 , 值越大 , 优先级越高 . 可以终止广播意图的继续传播 . 接收者可以篡改内容 .
广播的收发
该组件接收被广播的 intent,Context 可以通过 sendBroadcast() 和 sendOrderedBroadcast()
方法实现广播的发送 .
首先在需要发送信息的地方 ,把要发送的信息和用于过滤的信息 ( 如 Action 、 Category) 装入一个 Intent 对象 ,然后通过调用 Context.sendBroadcast() 、 sendOrderBroadcast() 或 sendStickyBroadcast() 方法,把 Intent 对象以广播方式发送出去。
使用 sendBroadcast() 或 sendStickyBroadcast() 方法发出去的 Intent ,所有满足条件的 BroadcastReceiver 都会随机地执行其 onReceive() 方法
普通广播的发送和接收:
sendBroadcast(intent);
Intent intent = new Intent( "cn.lenovo.yangguangf " );
sendBroadcast(intent);
priority :这个是 AndroidManifest.xml 中 intent-filter 的参数。
< receiver android:name = ".MyBroadcastReceiver" >
< intent-filter android:priority = "1000" >
< action android:name = "cn.lenovo.yangguangfu" />
</ intent-filter >
</ receiver >
sendOrderedBroadcast(intent, receiverPermission);
1 ,他决定该广播的级别,级别数值是在 -1000 到 1000 之间 , 值越大 , 优先级越高;
2 ,同级别接收是先后是随机的;级别低的收到广播;
3 ,在 android 系统中只要监听该广播的接收者,都能够收到 sendBroadcast(intent) 发出的广播 ;
3 ,不能截断广播的继续传播,
4 ,实验现象,在这个方法发来的广播中,代码注册方式中,收到的广播的先后和注明优先级最高的他们的先后是随机。如果都没有优先级,代码注册收到为最先。
有序广播的发送和接收:
sendOrderedBroadcast(intent, receiverPermission);
sendOrderedBroadcast(intent, receiverPermission, resultReceiver,
scheduler, initialCode, initialData, initialExtras)
意图,广播,所有匹配的这一意图将接收机接收广播。
receiverPermission 这是权限,一个接收器必须持以接收您的广播。如果为 null ,不经许可的要求。
resultReceiver
您自己
BroadcastReceiver
来当作最后的广播接收器。
调度自定义处理程序,用以安排
resultReceiver
回调
;
如果为
null
将语境中的主线程举行。
initialCode
一种结果代码的初始值。通常为
Activity.RESULT_OK
。这个值是
-1
;为其他
int
型
也可以,如
0,1,2
;
initialData
一种结果数据的初始值。通常情况下为空
,
是
String
类型
;
initialExtras
一种结果额外的初始值。通常情况下为空
,
是
Bundle;
intent The Intent to broadcast;
all receivers matching this Intent will receive the broadcast.
receiverPermission String naming
a permissions that a receiver must hold in order to receive your broadcast. If
null, no permission is required.
resultReceiver Your own
BroadcastReceiver to treat as the final receiver of the broadcast.
scheduler A custom Handler with
which to schedule the resultReceiver callback; if null it will be scheduled in
the Context's main thread.
initialCode An initial value for
the result code. Often Activity.RESULT_OK.
initialData An initial value for
the result data. Often null.
initialExtras An initial value
for the result extras. Often null.
1,
该广播的级别有级别之分,级别数值是在
-1000
到
1000
之间
,
值越大
,
优先级越高;
2,
同级别接收是先后是随机的,再到级别低的收到广播;
3,
同级别接收是先后是随机的,如果先接收到的把广播截断了,同级别的例外的接收者是无法收到该广播的。(
abortBroadcast()
)
4
,能截断广播的继续传播,高级别的广播收到该广播后,可以决定把该钟广播是否截断掉。
5
,实验现象,在这个方法发来的广播中,代码注册方式中,收到广播先后次序为:注明优先级的、代码注册的、没有优先级的;如果都没有优先级,代码注册收到为最先。
异步广播的发送和接收:
sendStickyBroadcast(intent);
当处理完之后的Intent
,依然存在,直到你把它去掉。
发这个广播需要权限<uses-permission android:name="android.permission.BROADCAST_STICKY"
/>
去掉是用这个方法removeStickyBroadcast(intent);
但别忘了在执行这个方法的应用里面
AndroidManifest.xml
同样要加上面的权限;
sendStickyOrderedBroadcast(intent,
resultReceiver, scheduler,
initialCode, initialData,
initialExtras)
这个方法具有有序广播的特性也有异步广播的特性;
发送这个广播要:
<uses-permission
android:name="android.permission.BROADCAST_STICKY"
/>
这个权限。才能使用这个方法。如果您并不拥有该权限,将抛出
SecurityException
的。
实验现象(
sendStickyOrderedBroadcast
()中),在这个方法发来的广播中,代码注册方式中,收到广播先后次序为:注明优先级的、代码注册的、没有优先级的;如果都没有优先级,代码注册收到为最先。
广播注册与注销
代码中注册广播:
注册广播方法一:
registerReceiver(BroadcastReceiver
receiver, IntentFilter filter)
,第一个参数是我们要处理广播的
BroadcastReceiver
(广播接收者,可以是系统的,也可以是自定义的);第二个参数是意图过滤器。
注册广播方法二:
registerReceiver(receiver, filter, broadcastPermission, scheduler)
,第一个参数是
BroadcastReceiver
(广播接收者,可以是系统的,也可以是自定义的);第二个参数是意图过滤器;第三个参数是广播权限;第四个参数是
Hander
;
注意:权限重复现象,如果功能清单文件里注册了权限,在该方法再注册,则
receiver
无法收到广播,如果
功能清单文件里没有注册了权限,该方法注册也无法收到。当该方法没有注册权限,功能清单里注册的时候,
receiver
能收到广播。
总结:在
Activity
中代码注册广播建议在:
onResume()
中注册;
思维拓展:
1
,如果在代码调用
registerReceiver(BroadcastReceiver
receiver, IntentFilter filter)
十次(
receiver
,
filter
的参数是同一参数),那么是否当该广播发送来的时候会收到十次呢?
2
,注销是否也要注销十次才能把广播全部注销呢?
系统中注册广播:(在
AndroidManifest.xml
中
)
<
receiver
android:name
=
".MyBroadcastReceiver"
>
<
intent-filter
android:priority
=
"900"
>
<
action
android:name
=
"cn.lenovo.yangguangfu"
/>
</
intent-filter
>
</
receiver
>
有时候还要根据发送广播是否指定权限,来决定是否要权限;
广播注销
//
代码中注销广播
/unregisterReceiver(mBatteryInfoReceiver);
在
Activity
中代码注销广播建议在:
onPuase()
中注销;
不要这这里面注销
Activity.onSaveInstanceState(),
因为这个方法是保存
Intent
状态的。
BroadCastReceiver
的
API
abortBroadcast
():
这个方法可以截获由
sendOrderedBroadcast
()
发送来的
广播,让其它广播接收者无法收到这个广播。
clearAbortBroadcast
()
这个方法是针对上面的
abortBroadcast()
方法的,用于取消截获广播。这样它的下一级广播接收者就能够收到该广播了。
getAbortBroadcast
()
这个方法作用是:判断是否调用了
abortBroadcast
(),如果先调用
abortBroadcast
(),接着再调用
getAbortBroadcast
(),将返回
true;
如果在调用
abortBroadcast()
、
clearAbortBroadcast
()
getAbortBroadcast
(),将返回
false;
public final boolean
getDebugUnregister
()
Since: API Level 1
Return the last value given to setDebugUnregister(boolean)
.
getResultCode
()
如果用下面四个方法发送得广播,返回码为:
-1
;
// sendBroadcast(intent);
// sendBroadcast(intent,
receiverPermission);
//
sendOrderedBroadcast(intent, receiverPermission);
// sendStickyBroadcast(intent);
如果用下面两个方法发送得广播,返回码为:根据你设置
initialCode
的数字是多少就是多少;
//
sendStickyOrderedBroadcast(intent, resultReceiver, scheduler,
// initialCode, initialData,
initialExtras)
//
sendOrderedBroadcast(intent, receiverPermission, resultReceiver,
// scheduler, initialCode, initialData,
initialExtras)
getResultData
()
得到发送广播时设置的
initialData
的数据;
getResultExtras
(boolean
makeMap)
If true then a new empty Map will be made
for you if the current Map is null; if false you should be prepared to receive
a null Map.
得到由
sendStickyOrderedBroadcast(intent,
resultReceiver, scheduler,
// initialCode, initialData,
initialExtras)
;
//
sendOrderedBroadcast(intent, receiverPermission, resultReceiver,
// scheduler, initialCode, initialData, initialExtras)
中
initialExtras
传入的参数。
实验:我用上面两个方法发了
initialExtras
(这个一个
Bundle
)传入的参数时,只要不为空,那么
makeMap
是否为
true
和
false
都能够得到数据。
isInitialStickyBroadcast
()
Returns true if the receiver is currently
processing the initial value of a sticky broadcast -- that is, the value that
was last broadcast and is currently held in the sticky cache, so this is not
directly the result of a broadcast right now.
如果广播接收者是目前处理的一个宿主的广播的初始值,将返回
true
,
-
也就是说,这个值是最后的广播出的值,目前正在举行的宿主缓存,所以这并不是直接导致了现在的广播。
实验:在第三个应用中调用这个方法,无论你用哪种方式发送广播,这个方法得到的总是
false
;在发送广播
的
resultReceiver
广播接收者里面调用,得到的也是
false
;
isOrderedBroadcast
()
sendStickyOrderedBroadcast(intent,
resultReceiver, scheduler,
initialCode, initialData, initialExtras)
上面这个方法发送时,得到的是
true;
判断是否是有序广播;
onReceive (Context context, Intent intent)
public IBinder peekService (Context myContext, Intent
service)
Provide a binder to an already-running service. This method is
synchronous and will not start the target service if it is not present, so it
is safe to call from onReceive.
Parameters:
myContext The Context that had been passed to onReceive(Context,
Intent)
service The Intent indicating the service you wish to use. See
Context.startService(Intent) for more information.
setDebugUnregister (boolean debug)
Control inclusion of debugging help for mismatched
calls to {@ Context#registerReceiver(BroadcastReceiver, IntentFilter)
Context.registerReceiver()}. If called with true, before given to
registerReceiver(), then the callstack of the following
Context.unregisterReceiver()
call is retained, to be printed if a later incorrect unregister
call is made. Note that doing this requires retaining information about the
BroadcastReceiver for
Android 中的BroadCastReceiver的更多相关文章
- android中的BroadCastReceiver
BroadCastReceiver组件本质是一种全局的监听器,用于监听系统全局的广播消息.由于BroadCastReceiver是一种全局的监听器,因此他可以非常方便的实现系统之间不同组件之间的通信. ...
- (转)Android 中LocalBroadcastManager的使用方式
发表于2个月前(2014-11-03 22:05) 阅读(37) | 评论(0) 0人收藏此文章, 我要收藏 赞0 1月10日 #长沙# OSC 源创会第32期开始报名 摘要 android中广播 ...
- Android中BroadcastReceiver的两种注册方式(静态和动态)详解
今天我们一起来探讨下安卓中BroadcastReceiver组件以及详细分析下它的两种注册方式. BroadcastReceiver也就是"广播接收者"的意思,顾名思义,它就是用来 ...
- Android中BroadcastReceiver广播
BroadCastReceiver 简介 广播接收者( BroadcastReceiver )用于接收广播 Intent ,广播 Intent 的发送是通过调用 Context.sendBroadca ...
- android 在基类activity中注册BroadcastReceiver,子activity类实现响应
android app 一般都会定义自己的BaseActivity, 如果各子Activity都需要接收广播但对广播的处理又不同时,可以考虑在BaseActivity中注册BroadcastRecei ...
- Android中BroadcastReceiver的使用
1.Android中广播分为静态注册和动态注册 2.下面是一个简单静态注册的例子 创建一个继承BroadcastReceiver的子类 public class DeviceBootReceiver ...
- Android中后台的劳动者“服务”
前言 作为四大组件之一的Service,想必不少开发者都是了解的,那具体熟悉吗?是不是对Service中的每个知识点是否了解,它与Activity的关系又是什么样的,我们所理解的后台服务跟Servic ...
- android 中调用接口发送短信
android中可以通过两种方式发送短信 第一:调用系统短信接口直接发送短信:主要代码如下: //直接调用短信接口发短信 SmsManager smsManager = SmsManager.getD ...
- 转:在Android中使用AlarmManager
原地址http://blog.csdn.net/maosidiaoxian/article/details/21776697 AlarmManager是Android中的一种系统级别的提醒服务,它会为 ...
随机推荐
- 安装RabbitMQ3.6.10报错:{error,{missing_dependencies,[crypto,ssl],
参考https://blog.csdn.net/u010739551/article/details/80848993 如果安装上篇博文安装则可避免这种情况 CentOS6.7安装RabbitMQ3. ...
- 011-JDK可视化监控工具-Jstat
一.概述 Jstat 是JDK自带的一个轻量级小工具.全称“Java Virtual Machine statistics monitoring tool”,它位于java的bin目录下,主要利用JV ...
- disruptor 高并发编程 简介demo
原文地址:http://www.cnblogs.com/qiaoyihang/p/6479994.html disruptor适用于大规模低延迟的并发场景.可用于读写操作分离.数据缓存,速度匹配(因为 ...
- 浅析造成 JS 内存泄露的几种原因及解决方案
内存泄露是指一块被分配的内存既不能使用,又不能回收,直到浏览器进程结束.在C++中,因为是手动管理内存,内存泄露是经常出现的事情.而现在流行的C#和Java等语言采用了自动垃圾回收方法管理内存,正常使 ...
- go——通道(二)
在Go语言里面,你不仅可以使用原子函数和互斥锁来保证对共享资源的安全访问以消除竞争状态, 还可以使用通道,通过发送和接收需要共享的资源,在goroutine之间做同步. 当一个资源需要在gorouti ...
- Django_内置Admin
Django内置Admin Django内置的Admin是对于model中对应的数据表进行增删改查提供的组件,使用方式有: 依赖APP: django.contrib.auth django.co ...
- Linux工作管理 jobs、fg、bg、nohup命令
概述 在Linux 中我们登陆了一个终端,已经在执行一个操作,可以通过一定的操作或命令在不关闭当前操作的情况下执行其他操作. 例如,我在当前终端正在 vi 一个文件,在不停止 vi 的情况下,如果我想 ...
- HTML5侧滑聊天面板
在线演示 本地下载
- 20145217《信网络对抗》逆向与BOF基础实践
20145217<信网络对抗>逆向与BOF基础实践 内容: 一.简单机器指令,汇编语言 1.'objdump -d xxx|more'反汇编命令查看机器代码,'cat'显示文件内容,'xx ...
- 20145219 《Java程序设计》第05周学习总结
20145219 <Java程序设计>第05周学习总结 教材学习内容总结 try.catch 1.求平均数程序示例 import java.util.Scanner; public cla ...