目录
-
Broadcast
-
概念
是一个全局的监听器,属于Android四大组件之一。Broadcast(广播)是一种广泛运用的在应用程序(APP)之间传输信息的机制。而BroadcastReceiver(广播接收器)是对发送出来的 广播进行过滤接受并响应的一类组件。
举例来说,Anddroid系统会在发生各种系统事件时发送广播,例如系统启动或设备开始充电时。再比如,应用可以发送自定义广播来通知其他应用它们可能感兴趣的事件(例如,一些新数据已下载)。
理解:android广播机制是android系统的全局事件,或系统事件。
观察者模式
观察者模式是定义对象间一对多的依赖关系。当被观察对象改变状态,所有注册了的观察者都会收到消息。
-
Broadcast作用:
监听 / 接收 应用发出的广播消息,并做出响应。
-
广播机制的三要素:
Android广播机制包含三个基本要素:
-
1、广播(Broadcast) - 用于发送广播。
-
2、广播接收器(BroadcastReceiver) - 用于接收广播。
-
3、意图内容(Intent)-用于保存广播相关信息的媒介。
-
广播机制的两步骤
创建广播接收器
Android为我们提供BroadcastReceiver组件来接收广播。
应用可以通过两种方式接收广播:清单文件声明的接收器(静态注册)和上下文注册的接收器(动态注册)。
注册广播接收器
静态注册:
step1:自定义一个广播接收器
public class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Toast.makeText(context, "ACTION_BOOT_COMPLETED", Toast.LENGTH_SHORT).show();
}
}
}
step2:静态注册方式是在AndroidManifest.xml的application里面定义receiver并设置要接收的action。
<receiver
android:name=".MyReceiver"
android:enabled="true">
<intent-filter >
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>
静态注册方式的特点:
-
如果您在清单文件中声明广播接收器,系统会在广播发出后启动您的应用(如果应用尚未运行)。
系统PackageManager会在应用安装时注册接收器。然后,该接收器会成为应用的一个独立入口点,这意味着如果应用当前未运行,系统可以启动应用并发送广播。
注意:API级别为26或更高的平台,则不能在清单文件中声明为隐式广播接收器(没有明确针对您的应用的广播),但一些不受此限制的系统隐式广播除外。
动态注册:
@Override
protected void onStart() {
super.onStart();
//step1 创建 BroadcastReceiver 的实例
if (mReceiver == null) {
mReceiver = new DynamicReceiver();
}
//step2 添加action
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
//step3 注册
registerReceiver(mReceiver, filter);
}
@Override
protected void onStop() {
super.onStop();
//注销
unregisterReceiver(mReceiver);
}
注意:本地广播只能动态注册 LocalBroadcastManager.getInstance(this).registerReceiver()
动态注册特点:
-
只要注册上下文有效,上下文注册的接收器就会接收广播。例如,如果您在
Activity
上下文中注册,只要 Activity 没有被销毁,您就会收到广播。如果您在Application上下文中注册,只要应用在运行,您就会收到广播。
注意:
注册和反注册在Activity生命周期中要成对出现。例如:onStart注册,onStop反注册。onResume注册,onPause反注册,以防多次注册接收器(如果您不想在暂停时接收广播,这样可以减少不必要的系统开销)。
-
发送广播:
Android 为应用提供三种方式来发送广播:
普通广播
sendOrderedBroadcast(Intent, String)
方法一次向一个接收器发送广播。当接收器逐个顺序执行时,接收器可以向下传递结果,也可以完全中止广播,使其不再传递给其他接收器。接收器的运行顺序可以通过匹配的 intent-filter 的 android:priority 属性来控制;具有相同优先级的接收器将按随机顺序运行。
普通广播特点:
-
普通广播通过Context.sendBroadcast()方法来发送。它是完全异步的。
-
所有的receivers接收器的执行顺序不确定。因此,所有的receivers接收器接收broadcast的顺序不确定。
-
这种方式效率更高。但是BroadcastReceiver无法使用setResult系列,getResult系列及abort系列API。
Intent intent = new Intent(Constant.ACTION_COMMON); intent.setPackage("com.pm.otherapp"); SendActivity.this.sendBroadcast(intent);
有序广播
sendBroadcast(Intent)
方法会按随机的顺序向所有接收器发送广播。这称为常规广播。这种方法效率更高,但也意味着接收器无法从其他接收器读取结果,无法传递从广播中收到的数据,也无法中止广播。
有序广播特点:
-
所有的receiver依次执行,即从优先级别最高的广播接收器开始接收,接收完了如果没有丢弃,就下传给下一个次高优先级别的广播接收器进行处理,依次类推,直到最后。
-
通过在intent-filter中设置android:priority属性来设置receiver的优先级。优先级相同的receiver其执行顺序不确定。
-
如果BroadcastReceiver是动态注册的话,且其intent-filter拥有相同android:priority属性的话,先注册的将先收到广播。
-
优先级的范围为-1000~1000之间
-
BroadcastReceiver可以使用setResult系列函数来将结果传给下一个BroadcastReceiver,通过getResult系列函数来取得上个BroadcastReceiver返回的结果,并可以用abort系列函数来让系统丢弃该广播,使该广播不再传送到别的BroadcastReceiver。
Intent intent = new Intent(Constant.ACTION_ORDER); intent.setPackage("com.pm.broadcastsimple"); SendActivity.this.sendOrderedBroadcast(intent, null);
本地广播
LocalBroadcastManager.sendBroadcast
方法会将广播发送给与发送器位于同一应用中的接收器。如果您不需要跨应用发送广播,请使用本地广播。这种实现方法的效率更高(无需进行进程间通信),而且您无需担心其他应用在收发您的广播时带来的任何安全问题。
本地广播特点:
-
如果您不需要跨应用发送广播,请使用本地广播。这种实现方法的效率更高(无需进行进程间通信),而且您无需担心其他应用在收发您的广播时带来的任何安全问题。
-
本地广播只能通过动态的方式注册,如果使用静态注册是无法接收到广播的。
Intent intent = new Intent(Constant.ACTION_LOCAL);
LocalBroadcastManager.getInstance(LocalActivity.this).sendBroadcast(intent);
-
为广播添加权限
-
发送广播时添加权限
发送广播时,除了通过 Action 筛选 Receiver,还可以 限制只有具有某种权限的应用才能接收。
step1:自定义接收需要的权限,发送广播时携带该权限参数,以筛选 Receiver 应用
<!--Manifest.xml-->
<permission android:name="com.pm.permission.receive"/>
//MainActivity.java
val intent = Intent(ACTION)
//FLAG_RECEIVER_INCLUDE_BACKGROUND, to send to static receiver
intent.addFlags(0x01000000)
//Receiver must have permission
sendBroadcast(intent, "com.pm.permission.receive")
step2:Receiver应用使用该权限
<!--Manifest.xml-->
<uses-permission android:name="com.pm.permission.receive"/>
-
接收广播时添加权限
对于广播接收者而言,除了通过 Action 筛选广播,还可以 限制只接收具有某种权限的应用发送的广播。
step1:接收方,自定义发送者应该具备的权限,接收广播时检查该权限,以筛选发送广播的应用。
<!--Manifest.xml-->
<permission android:name="com.pm.permission.receive"/>
//...
<receiver
android:name=".StaticReceiver"
android:enabled="true"
android:exported="true"
android:permission="com.pm.permission.send">
<intent-filter>
<action android:name="com.pm.broacast.one"/>
</intent-filter>
</receiver>
//MainActivity.java
//Sender must have permission
registerReceiver(registeredReceiver, IntentFilter(Constants.BROADCAST_ACTION),
Constants.SENDER_PERMISSION, null)
step2:发送广播的应用使用该权限
<!--Manifest.xml-->
<uses-permission android:name="com.pm.permission.send" />
-
系统广播
系统会在发生各种系统事件时自动发送广播,例如当系统进入和退出飞行模式时。系统广播会被发送给所有同意接收相关事件的应用。
-
Android系统广播大全
-
String ADD_SHORTCUT_ACTION 动作:在系统中添加一个快捷方式。
-
String ALL_APPS_ACTION 动作:列举所有可用的应用。输入:无。
-
String ALTERNATIVE_CATEGORY 类别:说明 activity 是用户正在浏览的数据的一个可选操作。
-
String ANSWER_ACTION 动作:处理拨入的电话。
-
String BATTERY_CHANGED_ACTION 广播:充电状态,或者电池的电量发生变化。
-
String BOOT_COMPLETED_ACTION 广播:在系统启动后,这个动作被广播一次(只有一次)。
-
String BROWSABLE_CATEGORY 类别:能够被浏览器安全使用的 activities 必须支持这个类别。
-
String BUG_REPORT_ACTION 动作:显示 activity 报告错误。
-
String CALL_ACTION 动作:拨打电话,被呼叫的联系人在数据中指定。
-
String CALL_FORWARDING_STATE_CHANGED_ACTION 广播:语音电话的呼叫转移状态已经改变。
-
String CLEAR_CREDENTIALS_ACTION 动作:清除登陆凭证 (credential)。
-
String CONFIGURATION_CHANGED_ACTION 广播:设备的配置信息已经改变,参见 Resources.Configuration.
-
Creator CREATOR 无 无
-
String DATA_ACTIVITY_STATE_CHANGED_ACTION 广播:电话的数据活动(data activity)状态(即收发数据的状态)已经改变。
-
String DATA_CONNECTION_STATE_CHANGED_ACTION 广播:电话的数据连接状态已经改变。
-
String DATE_CHANGED_ACTION 广播:日期被改变。
-
String DEFAULT_ACTION 动作:和 VIEW_ACTION 相同,是在数据上执行的标准动作。
-
String DEFAULT_CATEGORY 类别:如果 activity 是对数据执行确省动作(点击, center press)的一个选项,需要设置这个类别。
-
String DELETE_ACTION 动作:从容器中删除给定的数据。
-
String DEVELOPMENT_PREFERENCE_CATEGORY 类别:说明 activity 是一个设置面板 (development preference panel).
-
String DIAL_ACTION 动作:拨打数据中指定的电话号码。
-
String EDIT_ACTION 动作:为制定的数据显示可编辑界面。
-
String EMBED_CATEGORY 类别:能够在上级(父)activity 中运行。
-
String EMERGENCY_DIAL_ACTION 动作:拨打紧急电话号码。
-
int FORWARD_RESULT_LAUNCH 启动标记:如果这个标记被设置,而且被一个已经存在的 activity 用来启动新的 activity,已有 activity 的回复目标 (reply target) 会被转移给新的 activity。
-
String FOTA_CANCEL_ACTION 广播:取消所有被挂起的 (pending) 更新下载。
-
String FOTA_INSTALL_ACTION 广播:更新已经被确认,马上就要开始安装。
-
String FOTA_READY_ACTION 广播:更新已经被下载,可以开始安装。
-
String FOTA_RESTART_ACTION 广播:恢复已经停止的更新下载。
-
String FOTA_UPDATE_ACTION 广播:通过 OTA 下载并安装操作系统更新。
-
String FRAMEWORK_INSTRUMENTATION_TEST_CATEGORY 类别:To be used as code under test for framework instrumentation tests.
-
String GADGET_CATEGORY 类别:这个 activity 可以被嵌入宿主 activity (activity that is hosting gadgets)。
-
String GET_CONTENT_ACTION 动作:让用户选择数据并返回。
-
String HOME_CATEGORY 类别:主屏幕 (activity),设备启动后显示的第一个 activity。
-
String INSERT_ACTION 动作:在容器中插入一个空项 (item)。
-
String INTENT_EXTRA 附加数据:和 PICK_ACTIVITY_ACTION 一起使用时,说明用户选择的用来显示的 activity;和 ADD_SHORTCUT_ACTION 一起使用的时候,描述要添加的快捷方式。
-
String LABEL_EXTRA 附加数据:大写字母开头的字符标签,和 ADD_SHORTCUT_ACTION 一起使用。
-
String LAUNCHER_CATEGORY 类别:Activity 应该被显示在顶级的 launcher 中。
-
String LOGIN_ACTION 动作:获取登录凭证。
-
String MAIN_ACTION 动作:作为主入口点启动,不需要数据。
-
String MEDIABUTTON_ACTION 广播:用户按下了“Media Button”。
-
String MEDIA_BAD_REMOVAL_ACTION 广播:扩展介质(扩展卡)已经从 SD 卡插槽拔出,但是挂载点 (mount point) 还没解除 (unmount)。
-
String MEDIA_EJECT_ACTION 广播:用户想要移除扩展介质(拔掉扩展卡)。
-
String MEDIA_MOUNTED_ACTION 广播:扩展介质被插入,而且已经被挂载。
-
String MEDIA_REMOVED_ACTION 广播:扩展介质被移除。
-
String MEDIA_SCANNER_FINISHED_ACTION 广播:已经扫描完介质的一个目录。
-
String MEDIA_SCANNER_STARTED_ACTION 广播:开始扫描介质的一个目录。
-
String MEDIA_SHARED_ACTION 广播:扩展介质的挂载被解除 (unmount),因为它已经作为 USB 大容量存储被共享。
-
String MEDIA_UNMOUNTED_ACTION 广播:扩展介质存在,但是还没有被挂载 (mount)。
-
String MESSAGE_WAITING_STATE_CHANGED_ACTION 广播:电话的消息等待(语音邮件)状态已经改变。
-
int MULTIPLE_TASK_LAUNCH 启动标记:和 NEW_TASK_LAUNCH 联合使用,禁止将已有的任务改变为前景任务 (foreground)。
-
String NETWORK_TICKLE_RECEIVED_ACTION 广播:设备收到了新的网络 "tickle" 通知。
-
int NEW_TASK_LAUNCH 启动标记:设置以后,activity 将成为历史堆栈中的第一个新任务(栈顶)。
-
int NO_HISTORY_LAUNCH 启动标记:设置以后,新的 activity 不会被保存在历史堆栈中。
-
String PACKAGE_ADDED_ACTION 广播:设备上新安装了一个应用程序包。
-
String PACKAGE_REMOVED_ACTION 广播:设备上删除了一个应用程序包。
-
String PHONE_STATE_CHANGED_ACTION 广播:电话状态已经改变。
-
String PICK_ACTION 动作:从数据中选择一个项目 (item),将被选中的项目返回。
-
String PICK_ACTIVITY_ACTION 动作:选择一个 activity,返回被选择的 activity 的类(名)。
-
String PREFERENCE_CATEGORY 类别:activity是一个设置面板 (preference panel)。
-
String PROVIDER_CHANGED_ACTION 广播:更新将要(真正)被安装。
-
String PROVISIONING_CHECK_ACTION 广播:要求 polling of provisioning service 下载最新的设置。
-
String RUN_ACTION 动作:运行数据(指定的应用),无论它(应用)是什么。
-
String SAMPLE_CODE_CATEGORY 类别:To be used as an sample code example (not part of the normal user experience).
-
String SCREEN_OFF_ACTION 广播:屏幕被关闭。
-
String SCREEN_ON_ACTION 广播:屏幕已经被打开。
-
String SELECTED_ALTERNATIVE_CATEGORY 类别:对于被用户选中的数据,activity 是它的一个可选操作。
-
String SENDTO_ACTION 动作:向 data 指定的接收者发送一个消息。
-
String SERVICE_STATE_CHANGED_ACTION 广播:电话服务的状态已经改变。
-
String SETTINGS_ACTION 动作:显示系统设置。输入:无。
-
String SIGNAL_STRENGTH_CHANGED_ACTION 广播:电话的信号强度已经改变。
-
int SINGLE_TOP_LAUNCH 启动标记:设置以后,如果 activity 已经启动,而且位于历史堆栈的顶端,将不再启动(不重新启动) activity。
-
String STATISTICS_REPORT_ACTION 广播:要求 receivers 报告自己的统计信息。
-
String STATISTICS_STATE_CHANGED_ACTION 广播:统计信息服务的状态已经改变。
-
String SYNC_ACTION 动作:执行数据同步。
-
String TAB_CATEGORY 类别:这个 activity 应该在 TabActivity 中作为一个 tab 使用。
-
String TEMPLATE_EXTRA 附加数据:新记录的初始化模板。
-
String TEST_CATEGORY 类别:作为测试目的使用,不是正常的用户体验的一部分。
-
String TIMEZONE_CHANGED_ACTION 广播:时区已经改变。
-
String TIME_CHANGED_ACTION 广播:时间已经改变(重新设置)。
-
String TIME_TICK_ACTION 广播:当前时间已经变化(正常的时间流逝)。
-
String UMS_CONNECTED_ACTION 广播:设备进入 USB 大容量存储模式。
-
String UMS_DISCONNECTED_ACTION 广播:设备从 USB 大容量存储模式退出。
-
String UNIT_TEST_CATEGORY 类别:应该被用作单元测试(通过 test harness 运行)。
-
String VIEW_ACTION 动作:向用户显示数据。
-
String WALLPAPER_CATEGORY 类别:这个 activity 能过为设备设置墙纸。
-
String WALLPAPER_CHANGED_ACTION 广播:系统的墙纸已经改变。
-
String WALLPAPER_SETTINGS_ACTION 动作:显示选择墙纸的设置界面。输入:无。
-
String WEB_SEARCH_ACTION 动作:执行 web 搜索。
-
String XMPP_CONNECTED_ACTION 广播:XMPP 连接已经被建立。
-
String XMPP_DISCONNECTED_ACTION 广播:XMPP 连接已经被断开。