BroadcastReceiver概述
BroadcastReceiver,顾名思义就是“广播接收者”的意思,它是Android四大基本组件之一,这种组件本质上是一种全局的监听器,用于监听系统全局的广播消息。它可以接收来自系统和应用的的广播。广播之间信息的传递是通过Intent对象来传递的。
BroadcastReceiver是实现异步消息处理的组件。消息的实质就是Intent对象,因此可以通过附件携带消息。消息的来源有两个,一个是Android系统发出的系统事件消息,另一个是用户自定义的消息。消息的发送的模式有三种:正常、有序和持续(异步)。BroadcastReceiver必须先经过注册,才能够对消息进行处理。注册的方式有静态注册和动态注册两种。对于有序消息,动态注册的BroadcastReceiver总是先于静态注册的BroadcastReceiver被触发。对于同样级别的动态注册的BroadcastReceiver,优先级别高的将先触发,而静态注册的BroadcastReceiver总是按照静态注册的顺序执行。
BroadcastReceiver的生命周期很短,BroadcastReceiver在onReceiver返回后声明周期即结束,因此对于需要长时间处理的任务,如果采用子线程来处理的话,有可能子线程还没有结束BroadcastReceiver就先结束了。一旦BroadcastReceiver结束,此时它所在的进程就很容易在系统需要内存时被优先杀死,那么正在工作的子线程也会被杀死。那就悲剧了。所以,对于需要长时间处理的任务,一般是调用其他的Service组件来执行,而不是新开启一个线程。
BroadcastReceiver生命周期
BroadcastReceiver的生命周期比较简单,系统给予BroadcastReceiver的响应时间也才10s,当超出后,系统会直接报ANR(Application No Response)。每次广播到来时 , 会重新创建 BroadcastReceiver 对象 , 并且调用 onReceive() 方法 , 执行完以后 , 该对象即被销毁 . 当 onReceive() 方法在 10s 内没有执行完毕, Android 会认为该程序无响应 . 所以在BroadcastReceiver 里不能做一些比较耗时的操作 , 否侧会弹出 ANR 的对话框 。
BroadcastReceiver注册方式
静态注册就是在AndroidManifest.xml文件中定义,注册的广播接收器必须继承BroadReceiver。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="1"
android:versionName="1.0" package="com.bn.ex2_1">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Sample2_1_Activity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 注册自定义静态广播接收器 -->
<receiver android:name=".StaticReceiver">
<intent-filter>
<action android:name="com.bn.pp2.staticreceiver" />
</intent-filter>
</receiver>
</application>
</manifest>
动态注册就是在程序中使用Context.registerReceiver注册。
registerReceiver(BroadcastReceiver receiver, IntentFilter filter) ,第一个参数是我们要处理广播的 BroadcastReceiver (广播接收者,可以是系统的,也可以是自定义的);第二个参数是意图过滤器。
registerReceiver(receiver, filter, broadcastPermission, scheduler) ,第一个参数是 BroadcastReceiver (广播接收者,可以是系统的,也可以是自定义的);第二个参数是意图过滤器;第三个参数是广播权限;第四个参数是 Hander ;
注意:权限重复现象,如果功能清单文件里注册了权限,在该方法再注册,则 receiver 无法收到广播,如果功能清单文件里没有注册了权限,该方法注册也无法收到。当该方法没有注册权限,功能清单里注册的时候, receiver 能收到广播。
总结:在 Activity 中代码注册广播建议在: onResume() 中注册;
IntentFilter dynamic_filter = new IntentFilter();
dynamic_filter.addAction(DYNAMICACTION);//添加动态广播的Action
registerReceiver(dynamicReceiver, dynamic_filter);// 注册自定义动态广播消息
发送广播事件:通过Context.sendBroadcast来发送,由Intent来传递注册时用到的Action。
class DIYOnClickListener implements OnClickListener{//内部类OnClick监听器
public void onClick(View v) {
if(v.getId() == R.id.send_static){// 发送自定义静态注册广播消息
Intent intent = new Intent();
intent.setAction(STATICACTION);//设置Action
intent.putExtra("msg", "接收静态注册广播成功!"); //添加附加信息
sendBroadcast(intent);//发送Intent
}
else if(v.getId() == R.id.send_dynamic){// 发送自定义动态注册广播消息
Intent intent = new Intent();
intent.setAction(DYNAMICACTION);//设置Action
intent.putExtra("msg", "接收动态注册广播成功!");//添加附加信息
sendBroadcast(intent);//发送Intent
}}}
接收广播:当发送的广播被接收器监听到后,会调用onReceive()方法,并将包含消息的Intent对象传回。
public class StaticReceiver extends BroadcastReceiver {
@Override //静态广播接收器执行的方法
public void onReceive(Context context, Intent intent) {
String msg = intent.getStringExtra("msg");
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}}
private BroadcastReceiver dynamicReceiver = new BroadcastReceiver() {//动态广播的Receiver
@Override
public void onReceive(Context context, Intent intent) {
//动作检测
if(intent.getAction().equals(DYNAMICACTION)){
String msg = intent.getStringExtra("msg");
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
}
}
};
BroadcastReceiver注销
动态注册的注销
动态注册的BroadcastReceiver在使用的时候,在Activity进入停止或者销毁状态的时候使用unregisterReceiver方法将注册的BroadcastReceiver注销掉。在 Activity 中代码注销广播建议在onPuase() 中注销。
// 代码中注销广播
unregisterReceiver(mInfoReceiver);
静态注册的注销
当使用静态注册的BroadcastReceiver进行注销,根据官方API的说明:If this BroadcastReceiver was launched through a tag, then the object is no longer alive after returning from this function. This means you should not perform any operations that return a result to you asynchronously. (如果通过标签来注册的BroadcastReceiver,那么该对象的实例在onReceive被调用之后就会在任意时间内被销毁。)从而得出我们并不需要担心静态注册的BroadcastReceiver的销毁问题。
系统广播消息
系统广播被Android用来通知各应用组件一些重要的系统事件,被定义为android.content.intent中的Action常量:(注,默认的常量名前均为android.intent.action.XXXXX;有加前缀的分别为android.intent.category.BROWSABLE; android.server.checkin.XXXX。为了方便,统一到了一起,造成的不严谨,深表抱歉,但有好处。)
<receiver android:name=".MyReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_BROADCAST"/>
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
Action常量名称 | 系统实践描述 |
---|---|
ADD_SHORTCUT | 在系统中添加一个快捷方式 |
ALL_APPS | 列举所有可用的应用 |
ANSWER | 处理拨入的电话 |
BATTERY_CHANGED | 充电状态,或者电池的电量发生变化 |
BOOT_COMPLETED | 在系统启动后。 这个动作被广播一次(只有一次) |
category.BROWSABLE | 能够被浏览器安全使用的 activities 必须支持这个类别 |
BUG_REPORT | 显示 activity 报告错误 |
CALL | 拨打电话。被呼叫的联系人在数据中指定 |
CFF | 语音电话的呼叫转移状态已经改变 |
CLEAR_CREDENTIALS | 清除登陆凭证 |
CONFIGURATION_CHANGED | 设备的配置信息已经改变,参见 Resources.Configuration |
DATA_ACTIVITY | 电话的数据活动(data activity)状态(即收发数据的状态)已经改变 |
DATA_STATE | 电话的数据连接状态已经改变 |
DATE_CHANGED | 日期被改变 |
VIEW | 和 VIEW_ACTION 相同,是在数据上执行的标准动作 |
DELETE | 从容器中删除给定的数据 |
DIAL | 拨打数据中指定的电话号码 |
EDIT | 为制定的数据显示可编辑界面 |
EMERGENCY_DIAL | 拨打紧急电话号码 |
server.checkin.FOTA_CANCEL | 取消所有被挂起的更新下载 |
server.checkin.FOTA_INSTALL | 更新已经被确认,马上就要开始安装 |
server.checkin.FOTA_READY | 更新已经被下载。可以开始安装 |
server.checkin.FOTA_RESTART | 恢复已经停止的更新下载 |
server.checkin.FOTA_UPDATE | 通过 OTA 下载并安装操作系统更新 |
GET_CONTENT | 让用户选择数据并返回 |
INSERT | 在容器中插入一个空项 (item) |
LOGIN | 获取登录凭证 |
MAIN | 作为主入口点启动,不需要数据 |
MEDIABUTTON | 用户按下了“Media Button” |
MEDIA_BAD_REMOVAL | 扩展介质已经从 SD 卡插槽拔出,但是挂载点 还没解除 |
MEDIA_EJECT | 用户想要移除扩展介质(拔掉扩展卡) |
MEDIA_MOUNTED | 扩展介质被插入,而且已经被挂载 |
MEDIA_REMOVED | 扩展介质被移除 |
MEDIA_SCANNER_FINISHED | 已经扫描完介质的一个目录 |
MEDIA_SCANNER_STARTED | 开始扫描介质的一个目录 |
MEDIA_SHARED | 扩展介质的挂载被解除 。因为它已经作为 USB 大容量存储被共享 |
MEDIA_UNMOUNTED | 扩展介质存在,但是还没有被挂载 |
MWI | 电话的消息等待(语音邮件)状态已经改变 |
PACKAGE_ADDED | 设备上新安装了一个应用程序包 |
PACKAGE_REMOVED | 设备上删除了一个应用程序包 |
PHONE_STATE | 电话状态已经改变 |
PICK | 从数据中选择一个项目 ,将被选中的项目返回 |
PICK_ACTIVITY | 选择一个 activity,返回被选择的 activity 的类(名) |
PROVIDER_CHANGED | 更新将要(真正)被安装 |
PROVISIONING_CHECK | 要求 polling of provisioning service 下载最新的设置 |
RUN | 行数据(指定的应用),无论它(应用)是什么 |
SCREEN_OFF | 屏幕被关闭 |
SCREEN_ON | 屏幕已经被打开 |
SENDTO | 向 data 指定的接收者发送一个消息 |
SERVICE_STATE | 电话服务的状态已经改变 |
SETTINGS | 显示系统设置 |
SIG_STR | 电话的信号强度已经改变 |
STATISTICS_REPORT | 要求 receivers 报告自己的统计信息 |
STATISTICS_STATE_CHANGED | 统计信息服务的状态已经改变 |
SYNC | 执行数据同步 |
TIMEZONE_CHANGED | 时区已经改变 |
TIME_SET | 时间已经改变(重新设置) |
TIME_TICK | 当前时间已经变化(正常的时间流逝) |
UMS_CONNECTED | 设备进入 USB 大容量存储模式 |
UMS_DISCONNECTED | 设备从 USB 大容量存储模式退出 |
VIEW_ACTION | 向用户显示数据 |
WALLPAPER_CHANGED | 系统的墙纸已经改变 |
WALLPAPER_SETTINGS | 显示选择墙纸的设置界面 |
WEB_SEARCH | 执行 web 搜索 |
XMPP_CONNECTED | XMPP 连接已经被建立 |
XMPP_DI | XMPP 连接已经被断开 |
参考
版权申明:本文参考内容版权归原作者所有,感谢原作者的共享。
http://my.oschina.net/zhongwenhao/blog/143156
http://yangguangfu.iteye.com/blog/1063732