BroadcastReceiver的使用
广播的分类
- 普通广播
- 有序广播
- 粘性广播
- 本地广播
- 定向广播
广播接收者的注册
静态注册
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
<action android:name="android.intent.action.BATTERY_CHANGED" />
</intent-filter>
</receiver>
启用和禁止广播接收器
//启用广播接收器
private void enableBroadcastReceiver(Class<?> cls)
{
PackageManager packageManager = getPackageManager( );
packageManager.setComponentEnabledSetting(new ComponentName(this, cls),
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
//禁止广播接收器
private void disableBroadcastReceiver(Class<?> cls)
{
PackageManager packageManager = getPackageManager( );
packageManager.setComponentEnabledSetting(new ComponentName(this, cls),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
动态注册
- 注册
MyBroadcastReceiver receiver = new MyBroadcastReceiver(); IntentFilter filter = new IntentFilter(); filter.addAction("android.intent.action.TIME_TICK"); registerReceiver(receiver, filter);
- 解除注册
unregisterReceiver(receiver);
动态注册的广播接收器必须要组件销毁前进行解除注册
普通广播
- 普通广播是完全异步的
- 通过Context的
sendBroadcat()
函数来发送 - 消息传递的效率比较高,但是所有的receivers(接收器)的执行顺序不确定
- 接收者不能将处理结果传递给下一个接收者,并且无法终止广播Intent的传播
有序广播
- 有序广播通过Context的
sendOrderedBroadcast()
来发送 - 所有的广播接收器按照优先级依次执行,广播接收器的优先级通过receiver的intent-filter中的
android:priority
属性来设置,数值越大优先级越高。 - 当广播接收器接收的广播后,可以使用
setResult()
函数将结果传给下一个广播接收器接收,然后通过getResult()
函数来取得上个广播接收器返回的结果,并可以用abortBroadcast()
函数来让系统丢弃广播,使广播不再传送到别的广播接收器
有序广播的优先级
- 优先按
android:priority
来比较,数值越大则优先级越高,最大值为2147483647
(即int型的最大值,而非官方文档的1000) - 在
android:priority
相同的情况下,动态注册
优先级高于静态注册
- 在注册方式一样的情况下,
先注册
的优先级高于后注册
的
粘性广播
- API21上标记为过时
- 通过Context的
sendStickyBroadcast()
函数来发送。用此函数发送的广播会一直滞留,当有匹配此广播的广播接收器被注册后,该广播接收器就会收到此条广播。 - sendStickyBroadcast只保留最后一条广播,并且一直保留下去,这样即使已经有广播接收器处理了该广播,当再有匹配的广播接收器被注册时,此广播仍会被接收。如果只想处理一遍该广播,可以通过
removeStickyBroadcast()
函数实现 - 使用此函数发送广播时,需要获得B权限
<users-permission android:name="android.permission.BROADCAST_STICKY"/>
本地广播
- 在21版的Support4包中新增本地广播,也就是
LocalBroadcastManager
- 只需要调用context的sendBroadcast、registerReceiver、unregisterReceiver的地方替换为LocalBroadcastManager getInstance(Context context)中对应的函数即可
函数 | 作用 |
---|---|
LocalBroadcastManager.getInstance(context).registerReceiver(receiver,intentFilter) | 注册receiver |
LocalBroadcastManager.getInstance(context).unregisterReceiver(receiver) | 注销receiver |
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(HELLO_ACTON)) | 发送异步广播 |
LocalBroadcastManager.getInstance(context).sendBroadcastSync(new Intent()) | 发送同步广播 |
定向广播
- 定向广播是普通广播的一个变体
- 定向广播使用了intent-filter的一个特性,通过在Intent中设置ComponentName来显示指定接收器
public void sendDirectedBroadcast(String packageName,String className,String action)
{
Intent intent = new Intent(action);
intent.setComponent(new ComponentName(packageName,className));
sendBroadcast(intent);
}
`
权限设置
自定义权限
<permission android:name="com.android.permission.MYRECEIVER" android:protectionLevel="dangerous">
</permission>
申明权限
<uses-permission android:name="com.android.permission.MYRECEIVER"/>
发送权限
sendBroadcast(intent, "com.android.study.permission.MYRECEIVER");
静态注册带权限的广播接受者
<receiver android:name="com.android.receiver.PermissionBroadcastReceiver"
android:permission="com.android.permission.MYRECEIVER">
...
</receiver>
动态注册带权限的广播接受者
MyBroadcastReceiver receiver = new MyBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.TIME_TICK");
registerReceiver(receiver, filter,"com.android.permission.MYRECEIVER",null);
系统广播
BATTERY_CHANGED_ACTION
说明:充电状态,或者电池的电量发生变化。
action:”android.intent.action.BATTERY_CHANGED”BOOT_COMPLETED_ACTION
说明:在系统启动后,这个动作被广播一次(只有一次)。
action:”android.intent.action.BOOT_COMPLETED”CALL_FORWARDING_STATE_CHANGED_ACTION
说明:语音电话的呼叫转移状态已经改变。
action:”android.intent.action.CFF”CONFIGURATION_CHANGED_ACTION
说明:设备的配置信息已经改变
action:”android.intent.action.CONFIGURATION_CHANGED”DATA_ACTIVITY_STATE_CHANGED_ACTION
说明:电话的数据活动(data activity)状态(即收发数据的状态)已经改变。
action:”android.intent.action.DATA_ACTIVITY”DATA_CONNECTION_STATE_CHANGED_ACTION
说明:电话的数据连接状态已经改变。
action:”android.intent.action.DATA_STATE”DATE_CHANGED_ACTION
说明:日期被改变。
action:”android.intent.action.DATE_CHANGED”FOTA_CANCEL_ACTION
说明:取消所有被挂起的 (pending) 更新下载。
action:”android.server.checkin.FOTA_CANCEL”FOTA_INSTALL_ACTION
说明:更新已经被确认,马上就要开始安装。
action:”android.server.checkin.FOTA_INSTALL”FOTA_READY_ACTION
说明:更新已经被下载,可以开始安装。
action:”android.server.checkin.FOTA_READY”FOTA_RESTART_ACTION
说明:恢复已经停止的更新下载。
action:”android.server.checkin.FOTA_RESTART”FOTA_UPDATE_ACTION
说明:通过 OTA 下载并安装操作系统更新。
action:”android.server.checkin.FOTA_UPDATE”MEDIABUTTON_ACTION
说明:用户按下了“Media Button”。
action:”android.intent.action.MEDIABUTTON”MEDIA_BAD_REMOVAL_ACTION
说明:扩展介质(扩展卡)已经从 SD 卡插槽拔出,但是挂载点 (mount point) 还没解除 (unmount)。
action:”android.intent.action.MEDIA_BAD_REMOVAL”MEDIA_EJECT_ACTION
说明:用户想要移除扩展介质(拔掉扩展卡)。
action:”android.intent.action.MEDIA_EJECT”MEDIA_MOUNTED_ACTION
说明:扩展介质被插入,而且已经被挂载。
action:”android.intent.action.MEDIA_MOUNTED”MEDIA_REMOVED_ACTION
说明:扩展介质被移除。
action:”android.intent.action.MEDIA_REMOVED”MEDIA_SCANNER_FINISHED_ACTION
说明:已经扫描完介质的一个目录。
action:”android.intent.action.MEDIA_SCANNER_FINISHED”MEDIA_SCANNER_STARTED_ACTION
说明:开始扫描介质的一个目录。
action:”android.intent.action.MEDIA_SCANNER_STARTED”MEDIA_SHARED_ACTION
说明:扩展介质的挂载被解除 (unmount),因为它已经作为 USB 大容量存储被共享。
action:”android.intent.action.MEDIA_SHARED”MEDIA_UNMOUNTED_ACTION
说明:扩展介质存在,但是还没有被挂载 (mount)。
action:”android.intent.action.MEDIA_UNMOUNTED”MESSAGE_WAITING_STATE_CHANGED_ACTION
说明:电话的消息等待(语音邮件)状态已经改变。
action:”android.intent.action.MWI”NETWORK_TICKLE_RECEIVED_ACTION
说明:设备收到了新的网络 “tickle” 通知。
action:”android.intent.action.NETWORK_TICKLE_RECEIVED”PACKAGE_ADDED_ACTION
说明:设备上新安装了一个应用程序包。
action:”android.intent.action.PACKAGE_ADDED”PACKAGE_REMOVED_ACTION
说明:设备上删除了一个应用程序包。
action:”android.intent.action.PACKAGE_REMOVED”PHONE_STATE_CHANGED_ACTION
说明:电话状态已经改变。
action:”android.intent.action.PHONE_STATE”PROVIDER_CHANGED_ACTION
说明:更新将要(真正)被安装。
action:”android.intent.action.PROVIDER_CHANGED”PROVISIONING_CHECK_ACTION
说明:要求 polling of provisioning service 下载最新的设置。
action:”android.intent.action.PROVISIONING_CHECK”SCREEN_OFF_ACTION
说明:屏幕被关闭。
action:”android.intent.action.SCREEN_OFF”SCREEN_ON_ACTION
说明:屏幕已经被打开。
action:”android.intent.action.SCREEN_ON”SERVICE_STATE_CHANGED_ACTION
说明:电话服务的状态已经改变。
action:”android.intent.action.SERVICE_STATE”SIGNAL_STRENGTH_CHANGED_ACTION
说明:电话的信号强度已经改变。
action:”android.intent.action.SIG_STR”STATISTICS_REPORT_ACTION
说明:要求 receivers 报告自己的统计信息。
action:”android.intent.action.STATISTICS_REPORT”STATISTICS_STATE_CHANGED_ACTION
说明:统计信息服务的状态已经改变。
action:”android.intent.action.STATISTICS_STATE_CHANGED”TIMEZONE_CHANGED_ACTION
说明:时区已经改变。
action:”android.intent.action.TIMEZONE_CHANGED”TIME_CHANGED_ACTION
说明:时间已经改变(重新设置)。
action:”android.intent.action.TIME_SET”TIME_TICK_ACTION
说明:当前时间已经变化(正常的时间流逝)。
action:”android.intent.action.TIME_TICK”UMS_CONNECTED_ACTION
说明:设备进入 USB 大容量存储模式。
action:”android.intent.action.UMS_CONNECTED”UMS_DISCONNECTED_ACTION
说明:设备从 USB 大容量存储模式退出。
action:”android.intent.action.UMS_DISCONNECTED”WALLPAPER_CHANGED_ACTION
说明:系统的墙纸已经改变。
action:”android.intent.action.WALLPAPER_CHANGED”XMPP_CONNECTED_ACTION
说明:XMPP 连接已经被建立。
action:”android.intent.action.XMPP_CONNECTED”XMPP_DISCONNECTED_ACTION
说明:XMPP 连接已经被断开。
action:”android.intent.action.XMPP_DI说明:
无法收到系统广播
- android3.1以后,首次安装未启动或者用户强制force stop后,应用无法监听到系统广播
- 在Android3.1以后版本添加了标志
FLAG_INCLUDE_STOPPED_PACKAGES
和FLAG_EXCLUDE_STOPPED_PACKAGES
,用于区分发送广播时是否启动激活那些未启动过或者被用户force stop
的应用组件。当两个Flag都不设置或都设置的时候,默认操作是FLAG_INCLUDE_STOPPED_PACKAGES
。 - 系统向所有的Intent的广播添加了
FLAG_EXCLUDE_STOPPED_PACKAGES
标志。它这样做是为了防止广播无意中的或不必要地开启组件的stoppped应用程序的后台服务。这样可以优化系统性能,提高安全性。 - 用户给自定义的广播Intent添加
FLAG_INCLUDE_STOPPED_PACKAGES
,用于启动stop状态的应用组件。但是系统自带的广播intent,我们无能为力。 - 部分广播需要动态注册才有效,如时间变化等
- 部分广播需要设置addDataScheme,mediaScanner相关的需要设置
file
,package相关的需要设置package
,.sms相关的需要设置sms
参考资料
Android开发进阶从小工到专家
BroadcastReceiver应用详解
BroadcastReceiver中使用自定义Permission
Android静态注册无法接受系统广播问题
android.intent.action大全
Android的BroadcastReciver收不到Broadcast(系统广播)的原因之一
Android编程实战