一、广播简介
Android 应用与 Android 系统和其他 Android 应用之间可以相互收发广播消息,这与发布-订阅设计模式相似。这些广播会在所关注的事件发生时发送。举例来说,Android 系统会在发生各种系统事件时发送广播,例如系统启动或设备开始充电时。再比如,应用可以发送自定义广播来通知其他应用它们可能感兴趣的事件。
二、广播注册方式
自定义广播时我们只要继承BroadcastReceiver ,重写其onReceive方法即可
class CustomBroadCastReciver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
"接收到了广播".log()
}
}
- 静态注册
注册方式:在AndroidManifest.xml里通过<receive>标签声明
属性说明:
<receiver
android:enabled=["true" | "false"]
//此broadcastReceiver能否接收其他App的发出的广播
//默认值是由receiver中有无intent-filter决定的:如果有intent-filter,默认值为true,否则为false
android:exported=["true" | "false"]
android:icon="drawable resource"
android:label="string resource"
//继承BroadcastReceiver子类的类名
android:name=".mBroadcastReceiver"
//具有相应权限的广播发送者发送的广播才能被此BroadcastReceiver所接收;
android:permission="string"
//BroadcastReceiver运行所处的进程
//默认为app的进程,可以指定独立的进程
//注:Android四大基本组件都可以通过此属性指定自己的独立进程
android:process="string" >
监听本地语言改变
<receiver android:name=".CustomBroadCastReciver">
<intent-filter>
<action android:name="android.intent.action.BATTERY_CHANGED"/>
</intent-filter>
</receiver>
注意: 因为Android高版本限制了很多隐式广播静态注册,许多例如网络变化,锁屏等系统广播用户app将接收不到。这里的语言改变广播不在此限制。此外官方文档提供的以下广播皆不在此限制(需要梯子,文末我会列出)。
https://developer.android.com/guide/components/broadcast-exceptions?hl=zh-cn
- 动态注册
通过代码的方式设置intent-filter来添加其监听的方式为动态注册,动态注册可以监听一些被限制的静态广播,比如网络变化监听,代码如下
val broadCastReciver = CustomBroadCastReciver()
val intentFilter = IntentFilter()
//监听网络变化
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE")
registerReceiver(broadCastReciver,intentFilter)
注册完记得在合适的地方解注册
unregisterReceiver(broadCastReciver)
注意:动态广播最好在Activity 的 onResume()注册、onPause()注销。
在onResume()注册、onPause()注销是因为onPause()在App死亡前一定会被执行,从而保证广播在App死亡前一定会被注销,从而防止内存泄露。
三、发送广播-广播的种类
1. 普通广播
普通广播发送的方式通过sendBroadcast方法发送,传递参数为intent,通过intent的action来匹配广播,接收注册时静态、动态两种方式均可以
注册:
//注册方式一:动态注册
val intentFilter = IntentFilter()
intentFilter.addAction("customBroadCast")
registerReceiver(broadCastReciver,intentFilter)
//注册方式二:静态注册
<receiver android:name=".CustomBroadCastReciver">
<intent-filter>
<action android:name="customBroadCast"/>
</intent-filter>
</receiver>
val intent = Intent()
intent.setAction("customBroadCast")
//高版本必须要加,否则接收不到
intent.setComponent(ComponentName("com.czy.systemlearn","com.czy.systemlearn.CustomBroadCastReciver"))
sendBroadcast(intent)
2. 顺序广播
发送出去的广播被广播接收者按照先后顺序接收,先后顺序根据priority来决定
代码设置:intentFilter.priority = 1
xml设置: <intent-filter android:priority="1">
Priority属性相同者,动态注册的广播优先;
通过sendOrderedBroadcast(intent);发送即可
特点:
- 接收广播按顺序接收
- 先接收的广播接收者可以对广播进行截断,即后接收的广播接收者不再接收到此广播;
- 先接收的广播接收者可以对广播进行修改,那么后接收的广播接收者将接收到被修改后的广播
3. 本地广播
Android 中的广播默认是跨app通信,而跨app通信就存在效率低且有安全隐患,如果开启广播的意图不需要跨app,我们则可以使用本地广播。LocalBroadcastManager不能静态注册,只能动态注册
优势
1.只能传输在App内部,不会被其他App接收,确保数据安全
2.接收不到其他App广播,免干扰
3.比BrocastReceiver更加高效
使用
- 注册
val broadCastReciver = CustomBroadCastReciver()
val intentFilter = IntentFilter()
intentFilter.addAction("customBroadCast")
LocalBroadcastManager.getInstance(this).registerReceiver(broadCastReciver,intentFilter)
- 发送
val intent = Intent()
intent.setAction("customBroadCast")
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
- 解注册
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadCastReciver)
4. 系统广播
系统广播指的是,Android系统的一些状态发生改变时会向应用发送广播,比如开机,网络变化,电量变化,屏幕关闭打开等。
但是随着版本升级,越来愈多的系统广播被限制。下面是从官网介绍的版本改变更改
Android 7.0
Android 7.0(API 级别 24)及更高版本不发送以下系统广播:
- ACTION_NEW_PICTURE
-
ACTION_NEW_VIDEO
此外,以 Android 7.0 及更高版本为目标平台的应用必须使用 registerReceiver(BroadcastReceiver, IntentFilter)注册 CONNECTIVITY_ACTION 广播。无法在清单中声明接收器(静态注册)。
Android 8.0
从 Android 8.0(API 级别 26)开始,系统对清单声明的接收器施加了额外的限制。
如果您的应用以 Android 8.0 或更高版本为目标平台,那么对于大多数隐式广播,您不能使用清单来声明接收器,只能使用动态注册。
目前官网上还可以静态注册的广播如下:
ACTION_LOCKED_BOOT_COMPLETED、ACTION_BOOT_COMPLETED
豁免的原因这些广播仅在首次启动时发送一次,而且许多应用需要接收此广播以调度作业、闹钟等。
ACTION_USER_INITIALIZE、"android.intent.action.USER_ADDED"、"android.intent.action.USER_REMOVED"
这些广播受特许权限保护,因此大多数普通应用都无法接收它们。
"android.intent.action.TIME_SET"、ACTION_TIMEZONE_CHANGED、ACTION_NEXT_ALARM_CLOCK_CHANGED
当时间、时区或闹钟发生更改时,时钟应用可能需要接收这些广播以更新闹钟。
ACTION_LOCALE_CHANGED
仅在语言区域发生更改时发送,这种情况并不常见。当语言区域发生更改时,应用可能需要更新其数据。
ACTION_USB_ACCESSORY_ATTACHED、ACTION_USB_ACCESSORY_DETACHED、ACTION_USB_DEVICE_ATTACHED、ACTION_USB_DEVICE_DETACHED
如果某个应用需要了解这些与 USB 有关的事件,除了为广播进行注册,目前还没有很好的替代方法。
ACTION_CONNECTION_STATE_CHANGED、ACTION_CONNECTION_STATE_CHANGED、ACTION_ACL_CONNECTED、ACTION_ACL_DISCONNECTED
如果应用接收到针对这些蓝牙事件的广播,则用户体验不太可能受到影响。
ACTION_CARRIER_CONFIG_CHANGED、TelephonyIntents.ACTION_*_SUBSCRIPTION_CHANGED、"TelephonyIntents.SECRET_CODE_ACTION"、ACTION_PHONE_STATE_CHANGED、ACTION_PHONE_ACCOUNT_REGISTERED、ACTION_PHONE_ACCOUNT_UNREGISTERED
OEM 电话应用可能需要接收这些广播。
LOGIN_ACCOUNTS_CHANGED_ACTION
有些应用需要了解登录帐号的更改,以便为新帐号和已更改的帐号设置调度的操作。
ACTION_ACCOUNT_REMOVED
具有帐号可见性的应用会在帐号被移除后收到此广播。如果应用只需要对此帐号更改执行操作,则强烈建议应用使用此广播,而不是使用已弃用的 LOGIN_ACCOUNTS_CHANGED_ACTION。
ACTION_PACKAGE_DATA_CLEARED
仅在用户明确清除“设置”中的数据时发送,因此广播接收器不太可能对用户体验造成显著影响。
ACTION_PACKAGE_FULLY_REMOVED
某些应用可能需要在其他软件包被移除时更新其存储的数据;对于这些应用来说,除了为此广播进行注册,没有很好的替代方法。
注意:其他与软件包相关的广播(例如 ACTION_PACKAGE_REPLACED)未能免受新限制的约束。这些广播很常见,豁免的话可能会影响性能。
ACTION_NEW_OUTGOING_CALL
应用需要接收此广播,以在用户拨打电话时采取相应操作。
ACTION_DEVICE_OWNER_CHANGED
此直播的发送频率不高;某些应用需要接收它来了解设备的安全状态已发生更改。
ACTION_EVENT_REMINDER
由日历提供程序发送,以向日历应用发布事件提醒。由于日历提供程序并不知道日历应用是什么,因此此广播必须是隐式的。
ACTION_MEDIA_MOUNTED、ACTION_MEDIA_CHECKING、ACTION_MEDIA_UNMOUNTED、ACTION_MEDIA_EJECT、ACTION_MEDIA_UNMOUNTABLE、ACTION_MEDIA_REMOVED、ACTION_MEDIA_BAD_REMOVAL
这些广播会在用户与设备的物理互动(安装或移除存储卷)或启动初始化(可用卷装载时)过程中发送,并且通常受用户控制。
SMS_RECEIVED_ACTION、WAP_PUSH_RECEIVED_ACTION
短信接收者应用需要依赖这些广播。
网友评论