BroadcastReceiver的使用

Author Avatar
罗炜光 8月 27, 2016
  • 在其它设备中阅读本文章

广播的分类

  • 普通广播
  • 有序广播
  • 粘性广播
  • 本地广播
  • 定向广播

广播接收者的注册

静态注册

<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);

系统广播

  1. BATTERY_CHANGED_ACTION
    说明:充电状态,或者电池的电量发生变化。
    action:”android.intent.action.BATTERY_CHANGED”

  2. BOOT_COMPLETED_ACTION
    说明:在系统启动后,这个动作被广播一次(只有一次)。
    action:”android.intent.action.BOOT_COMPLETED”

  3. CALL_FORWARDING_STATE_CHANGED_ACTION
    说明:语音电话的呼叫转移状态已经改变。
    action:”android.intent.action.CFF”

  4. CONFIGURATION_CHANGED_ACTION
    说明:设备的配置信息已经改变
    action:”android.intent.action.CONFIGURATION_CHANGED”

  5. DATA_ACTIVITY_STATE_CHANGED_ACTION
    说明:电话的数据活动(data activity)状态(即收发数据的状态)已经改变。
    action:”android.intent.action.DATA_ACTIVITY”

  6. DATA_CONNECTION_STATE_CHANGED_ACTION
    说明:电话的数据连接状态已经改变。
    action:”android.intent.action.DATA_STATE”

  7. DATE_CHANGED_ACTION
    说明:日期被改变。
    action:”android.intent.action.DATE_CHANGED”

  8. FOTA_CANCEL_ACTION
    说明:取消所有被挂起的 (pending) 更新下载。
    action:”android.server.checkin.FOTA_CANCEL”

  9. FOTA_INSTALL_ACTION
    说明:更新已经被确认,马上就要开始安装。
    action:”android.server.checkin.FOTA_INSTALL”

  10. FOTA_READY_ACTION
    说明:更新已经被下载,可以开始安装。
    action:”android.server.checkin.FOTA_READY”

  11. FOTA_RESTART_ACTION
    说明:恢复已经停止的更新下载。
    action:”android.server.checkin.FOTA_RESTART”

  12. FOTA_UPDATE_ACTION
    说明:通过 OTA 下载并安装操作系统更新。
    action:”android.server.checkin.FOTA_UPDATE”

  13. MEDIABUTTON_ACTION
    说明:用户按下了“Media Button”。
    action:”android.intent.action.MEDIABUTTON”

  14. MEDIA_BAD_REMOVAL_ACTION
    说明:扩展介质(扩展卡)已经从 SD 卡插槽拔出,但是挂载点 (mount point) 还没解除 (unmount)。
    action:”android.intent.action.MEDIA_BAD_REMOVAL”

  15. MEDIA_EJECT_ACTION
    说明:用户想要移除扩展介质(拔掉扩展卡)。
    action:”android.intent.action.MEDIA_EJECT”

  16. MEDIA_MOUNTED_ACTION
    说明:扩展介质被插入,而且已经被挂载。
    action:”android.intent.action.MEDIA_MOUNTED”

  17. MEDIA_REMOVED_ACTION
    说明:扩展介质被移除。
    action:”android.intent.action.MEDIA_REMOVED”

  18. MEDIA_SCANNER_FINISHED_ACTION
    说明:已经扫描完介质的一个目录。
    action:”android.intent.action.MEDIA_SCANNER_FINISHED”

  19. MEDIA_SCANNER_STARTED_ACTION
    说明:开始扫描介质的一个目录。
    action:”android.intent.action.MEDIA_SCANNER_STARTED”

  20. MEDIA_SHARED_ACTION
    说明:扩展介质的挂载被解除 (unmount),因为它已经作为 USB 大容量存储被共享。
    action:”android.intent.action.MEDIA_SHARED”

  21. MEDIA_UNMOUNTED_ACTION
    说明:扩展介质存在,但是还没有被挂载 (mount)。
    action:”android.intent.action.MEDIA_UNMOUNTED”

  22. MESSAGE_WAITING_STATE_CHANGED_ACTION
    说明:电话的消息等待(语音邮件)状态已经改变。
    action:”android.intent.action.MWI”

  23. NETWORK_TICKLE_RECEIVED_ACTION
    说明:设备收到了新的网络 “tickle” 通知。
    action:”android.intent.action.NETWORK_TICKLE_RECEIVED”

  24. PACKAGE_ADDED_ACTION
    说明:设备上新安装了一个应用程序包。
    action:”android.intent.action.PACKAGE_ADDED”

  25. PACKAGE_REMOVED_ACTION
    说明:设备上删除了一个应用程序包。
    action:”android.intent.action.PACKAGE_REMOVED”

  26. PHONE_STATE_CHANGED_ACTION
    说明:电话状态已经改变。
    action:”android.intent.action.PHONE_STATE”

  27. PROVIDER_CHANGED_ACTION
    说明:更新将要(真正)被安装。
    action:”android.intent.action.PROVIDER_CHANGED”

  28. PROVISIONING_CHECK_ACTION
    说明:要求 polling of provisioning service 下载最新的设置。
    action:”android.intent.action.PROVISIONING_CHECK”

  29. SCREEN_OFF_ACTION
    说明:屏幕被关闭。
    action:”android.intent.action.SCREEN_OFF”

  30. SCREEN_ON_ACTION
    说明:屏幕已经被打开。
    action:”android.intent.action.SCREEN_ON”

  31. SERVICE_STATE_CHANGED_ACTION
    说明:电话服务的状态已经改变。
    action:”android.intent.action.SERVICE_STATE”

  32. SIGNAL_STRENGTH_CHANGED_ACTION
    说明:电话的信号强度已经改变。
    action:”android.intent.action.SIG_STR”

  33. STATISTICS_REPORT_ACTION
    说明:要求 receivers 报告自己的统计信息。
    action:”android.intent.action.STATISTICS_REPORT”

  34. STATISTICS_STATE_CHANGED_ACTION
    说明:统计信息服务的状态已经改变。
    action:”android.intent.action.STATISTICS_STATE_CHANGED”

  35. TIMEZONE_CHANGED_ACTION
    说明:时区已经改变。
    action:”android.intent.action.TIMEZONE_CHANGED”

  36. TIME_CHANGED_ACTION
    说明:时间已经改变(重新设置)。
    action:”android.intent.action.TIME_SET”

  37. TIME_TICK_ACTION
    说明:当前时间已经变化(正常的时间流逝)。
    action:”android.intent.action.TIME_TICK”

  38. UMS_CONNECTED_ACTION
    说明:设备进入 USB 大容量存储模式。
    action:”android.intent.action.UMS_CONNECTED”

  39. UMS_DISCONNECTED_ACTION
    说明:设备从 USB 大容量存储模式退出。
    action:”android.intent.action.UMS_DISCONNECTED”

  40. WALLPAPER_CHANGED_ACTION
    说明:系统的墙纸已经改变。
    action:”android.intent.action.WALLPAPER_CHANGED”

  41. XMPP_CONNECTED_ACTION
    说明:XMPP 连接已经被建立。
    action:”android.intent.action.XMPP_CONNECTED”

  42. XMPP_DISCONNECTED_ACTION
    说明:XMPP 连接已经被断开。
    action:”android.intent.action.XMPP_DI说明:

无法收到系统广播

  • android3.1以后,首次安装未启动或者用户强制force stop后,应用无法监听到系统广播
  • 在Android3.1以后版本添加了标志FLAG_INCLUDE_STOPPED_PACKAGESFLAG_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官方API说明

参考资料

Android开发进阶从小工到专家
BroadcastReceiver应用详解
BroadcastReceiver中使用自定义Permission
Android静态注册无法接受系统广播问题
android.intent.action大全
Android的BroadcastReciver收不到Broadcast(系统广播)的原因之一
Android编程实战