博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android BroadCastReceiver介绍
阅读量:5320 次
发布时间:2019-06-14

本文共 5765 字,大约阅读时间需要 19 分钟。

本文主要简单的讨论下Android中广播发送与注册的多种方式

注册广播接收者有两种方式,动态与静态:

1,动态注册:在Activity的onCreate方法中或根据需要调用register()方法注册即可动态注册一个广播接收者,在代码中有关于其特点的简单注释,如下

private void register() {
ReceiverTool rt = new ReceiverTool(); IntentFilter filter = new IntentFilter(); filter.addAction("com.xiaomo.view.broadcast01"); registerReceiver(rt, filter); } /** * 动态注册 -- 接收广播 * 每次接收广播使用的是同一个接收实例,并不会每次都创建一个实例 * @author Administrator * */ class ReceiverTool extends BroadcastReceiver {
public ReceiverTool () {
// Log.i(Constant.TAG, "创建了ReceiverTool的一个实例"); } @Override public void onReceive(Context context, Intent intent) {
Log.i(Constant.TAG, "" + this.hashCode()); Log.i(Constant.TAG, "接到到广播, ACTION = " + intent.getAction()); } }

2,静态注册,自定义一个class extends BroadcastReceiver,然后在mainfest.xml中使用<receiver...>标签的形式注册,特性同样注释在代码中:

/**  * 静态注册(mainfest.xml) -- 接收广播  * 每次接收到相应的广播,都会创建一个接收器的实例,这一点与动态注册不同  * 之所以这样设计,个人认为实属无奈,因为在mainfest.xml中注册了一个接收者,相当于一个标记  * 但系统无法知道什么时候会接收到对应的广播  * 1,系统在扫描到配置文件中注册了接收者时,就为其创建对象 (不知道什么时候会接收到广播)  * 2,系统在该接收者接收到广播时,第一次为其创建对象 (不知道什么时候会再次接收到广播)  * 如果这两种情况下,都在内存中保存这个接收者对象,那么就会出现对应的括号中场景  * 并且一直保存在内存中,明显占内存,浪费内存资源(一个接收者无关紧要,但若一个应用中有10, 100..个静态广播接收者,你懂的!)  * 所以不能采用这样的设计,而采用每次接收到广播,就为其创建对象,用完就清掉  * 而且在处理接收广播过程中,Android还加上了超时限制(ANR异常,因为BroadcastReceiver默认运行在UI主线程中)  * @author Administrator  *  */ public class StaticReceiverTool extends BroadcastReceiver{
public StaticReceiverTool() {
// Log.i(Constant.TAG, "创建了StaticReceiverTool的一个实例"); } @Override public void onReceive(Context context, Intent intent) {
// Log.i(Constant.TAG, "" + this.hashCode()); Log.i(Constant.TAG, "StaticReceiverTool接到到广播, ACTION = " + intent.getAction()); } }

mainfest.xml:

 

广播接收者可以接收系统自带的广播,也可以接收自定义的广播

那么相应的,Intent中的action可以自定义也可以是使用系统相应服务特定的action

自定义的广播发送方式一般如下:

Intent intent = new Intent("com.xiaomo.view.broadcast01");                 sendBroadcast(intent); //                sendBroadcast(intent);连续发送两次,那么接收者就会连续接收两次同样的广播

对于多个广播接收者接收同一个广播,会涉及到优先级priority的概念,下面再定义一个broadcastReceiver(动态与静态的区别上面已经说过,这里采用静态的方式):

public class StaticReceiverTool02 extends BroadcastReceiver {
public StaticReceiverTool02() {
} @Override public void onReceive(Context context, Intent intent) {
Log.i(Constant.TAG, "StaticReceiverTool02接到到广播, ACTION = " + intent.getAction()); // 接收non-ordered广播时,如果调用方法终止广播 // 会报异常:BroadcastReceiver trying to return result during a non-ordered // broadcast // this.abortBroadcast(); }

其对应的xml中得配置:

注意StaticReceiverTool02这个receiver的配置中加了优先级android:priority="10",那么使用上面的代码发送广播后,Log中的状态为:

StaticReceiverTool02接到到广播, ACTION = com.xiaomo.view.broadcast01

StaticReceiverTool接到到广播, ACTION = com.xiaomo.view.broadcast01

因为StaticReceiverTool02的优先级priority = 10 比StaticReceiverTool的0高(如果不加优先级设置,两者几乎同时收到广播,没有固定的顺序)

在android系统中默认的优先级 = 0, 优先级的范围为-1000 ~ 1000,最高的优先级为1000.

如果想终止广播,可以调用abortBroadcast();方法,但上面的示例中无论在哪个接收者中调用,都会出现异常(见code注释),这涉及到android系统中几种不同的广播发送方式,而若使用上面代码中的发送方式sendBroadcast(intent),则接收者在处理过程中是不能终止广播的继续传递的,这个在源码中明确说明。

 

接下来讨论下广播的几种发送方式:

1, 就是上面说到的常用方式:sendBroadcast(intent);

2, 有序广播 sendOrderedBroadcast(intent, "com.xiaomo");  (有序的广播可以使用abortBroadcast()终止广播)

第二个参数为权限控制,无权限就写null即可

当然若加了权限,则必须在maifest.xml中申明权限且设置接收权限

<uses-permission android:name="com.xiaomo" />

<permission android:name="com.xiaomo" android:protectionLevel="normal"></permission>

这样才可以接收到广播,此时若在StaticReceiverTool02的onReceiver()中加入代码this.abortBroadcast();

那么StaticReceiverTool就接收不到这个广播了.

 

3,sendStickyBroadcast(intent);

这个不涉及到自定义权限,但是需要在配置文件中设置使用权限:<uses-permission android:name="android.permission.BROADCAST_STICKY"/>

这种方式也同样不能在接收过程中,终止广播.

这种方式的特殊之处在于,广播发送出去后,即使没有对应的接收者,内存中也会缓存这个广播,在未删除之前,一旦有相应的接收者注册,那么这个接收者就会收到这个广播

还使用上面的例子,把action改一下即可(此段代码在activity的oncreate(...)中):

new Handler().postDelayed(new Runnable() {
@Override public void run() {
register(); } }, 30000); // new Handler().postDelayed(new Runnable() {
// @Override // public void run() {
// // register(); // } // }, 20000); Button button = (Button) findViewById(R.id.button1); button.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
Intent intent = new Intent("com.xiaomo.view.broadcast02"); sendStickyBroadcast(intent); Log.i(Constant.TAG, "广播发送完毕"); } });

把上面register()方法中action的string值改成对应的02(额,主要是不想动配置文件了,不然好几个接收者接收同一个广播,对比的不清楚)

filter.addAction("com.xiaomo.view.broadcast02");

运行后,先点击button发送广播,可以发现log中只显示了“广播发送完毕”,等待大约30秒后,会显示“接收到广播。。。。”

即通过sendStickyBroadcast(intent)发送的广播先缓存在内存中,30秒后子线程执行注册广播接收者的代码,然后这个接收者就会立即接收到...broadcast02这个广播

当然也可以从内存中将这个缓存的广播删除:

@Override         public void onReceive(Context context, Intent intent) {
removeStickyBroadcast(intent);//删除在内存中的广播 Log.i(Constant.TAG, "" + this.hashCode()); Log.i(Constant.TAG, "接到到广播, ACTION = " + intent.getAction()); }

这样其他可以接收到这个广播的接收者就不会接收到这个广播了(当然当前的receiver得比其他receiver先接收到这个广播, 顺序问题又涉及到上面的有序/无序,优先级的问题了)

 

4,还有一种比较蛋疼的方式:sendStickyOrderedBroadcast(Intent intent,

BroadcastReceiver resultReceiver,

Handler scheduler, int initialCode, String initialData,
Bundle initialExtras)

。。。哈哈,好吧,我承认,这个我看了一眼,就没看过第二眼(当然也从来没见过哪里使用这种方式发送广播的....)

 

转载自:

转载于:https://www.cnblogs.com/maydow/p/4740689.html

你可能感兴趣的文章
疫情控制
查看>>
YUI3自动加载树实现
查看>>
python知识思维导图
查看>>
当心JavaScript奇葩的逗号表达式
查看>>
App Store最新审核指南(2015年3月更新版)
查看>>
织梦MIP文章内容页图片适配百度MIP规范
查看>>
第13课 - 自动生成依赖关系(下)
查看>>
POJ No.2386【B007】
查看>>
点击复制插件clipboard.js
查看>>
[Kali_BT]通过低版本SerialPort蓝牙渗透功能手机
查看>>
Oracle命令--创建表空间、创建临时表空间、创建用户
查看>>
poj2187 Beauty Contest
查看>>
iOS开发之使用XMPPFramework实现即时通信(一)
查看>>
CentOS 6.5(x86_32)下安装Oracle 10g R2
查看>>
C语言学习总结(三) 复杂类型
查看>>
HNOI2018
查看>>
【理财】关于理财的网站
查看>>
Ubunt中文乱码
查看>>
《当幸福来敲门》读后
查看>>
【转】系统无法进入睡眠模式解决办法
查看>>