Android 四大组件之一 :BroadCastReceiver 广播接收器详解

转自:

http://yangguangfu.iteye.com/blog/1063732

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 NoResponse)的对话框.。

怎么用好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的参数。


<receiverandroid:name=".MyBroadcastReceiver">

<intent-filterandroid:priority="1000">


<actionandroid: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;

English:
intent :The Intent to broadcast;all receivers matching this Intent will receive the broadcast.

receiverPermission: String naminga permissions that a receiver must hold in order to receive your broadcast. Ifnull, no permission is required.

resultReceiver: Your ownBroadcastReceiver to treat as the final receiver of the broadcast.

scheduler: A custom Handler withwhich to schedule the resultReceiver callback; if null it will be scheduled inthe Context’s main thread.

initialCode :An initial value forthe result code. Often Activity.RESULT_OK.

initialData :An initial value forthe result data. Often null.

initialExtras :An initial valuefor the result extras. Often null.

1,该广播的级别有级别之分,级别数值是在-1000到1000之间,值越大,优先级越高;

2,同级别接收是先后是随机的,再到级别低的收到广播;

3,同级别接收是先后是随机的,如果先接收到的把广播截断了,同级别的例外的接收者是无法收到该广播的。(abortBroadcast())

4,能截断广播的继续传播,高级别的广播收到该广播后,可以决定把该钟广播是否截断掉。

5,实验现象,在这个方法发来的广播中,代码注册方式中,收到广播先后次序为:注明优先级的、代码注册的、没有优先级的;如果都没有优先级,代码注册收到为最先。

异步广播的发送和接收:

sendStickyBroadcast(intent);

当处理完之后的Intent,依然存在,直到你把它去掉。

发这个广播需要权限

去掉是用这个方法removeStickyBroadcast(intent);但别忘了在执行这个方法的应用里面AndroidManifest.xml同样要加上面的权限;

sendStickyOrderedBroadcast(intent,resultReceiver, scheduler,

initialCode, initialData,initialExtras)

这个方法具有有序广播的特性也有异步广播的特性;

发送这个广播要:

广播注册与注销

代码中注册广播:

注册广播方法一:registerReceiver(BroadcastReceiverreceiver, IntentFilter filter),第一个参数是我们要处理广播的BroadcastReceiver(广播接收者,可以是系统的,也可以是自定义的);第二个参数是意图过滤器。

注册广播方法二:registerReceiver(receiver, filter, broadcastPermission, scheduler),第一个参数是BroadcastReceiver(广播接收者,可以是系统的,也可以是自定义的);第二个参数是意图过滤器;第三个参数是广播权限;第四个参数是Hander;

注意:权限重复现象,如果功能清单文件里注册了权限,在该方法再注册,则receiver无法收到广播,如果功能清单文件里没有注册了权限,该方法注册也无法收到。当该方法没有注册权限,功能清单里注册的时候,receiver能收到广播。

总结:在Activity中代码注册广播建议在:onResume()中注册;

思维拓展:1,如果在代码调用registerReceiver(BroadcastReceiverreceiver, IntentFilter filter)十次(receiver,filter的参数是同一参数),那么是否当该广播发送来的时候会收到十次呢?

2,注销是否也要注销十次才能把广播全部注销呢?

系统中注册广播:在AndroidManifest.xml中

<receiverandroid:name=".MyBroadcastReceiver">

<intent-filterandroid:priority="900">


<actionandroid: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(booleanmakeMap)

If true then a new empty Map will be madefor you if the current Map is null; if false you should be prepared to receivea 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 currentlyprocessing the initial value of a sticky broadcast – that is, the value thatwas last broadcast and is currently held in the sticky cache, so this is notdirectly the result of a broadcast right now.

如果广播接收者是目前处理的一个宿主的广播的初始值,将返回true,- 也就是说,这个值是最后的广播出的值,目前正在举行的宿主缓存,所以这并不是直接导致了现在的广播。

实验:在第三个应用中调用这个方法,无论你用哪种方式发送广播,这个方法得到的总是false;在发送广播的resultReceiver广播接收者里面调用,得到的也是false;

isOrderedBroadcast()

sendStickyOrderedBroadcast(intent,resultReceiver, scheduler,

initialCode, initialData, initialExtras)

上面这个方法发送时,得到的是true;

判断是否是有序广播;

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值