1、广播的类型
广播分为标准广播和有序广播。
1.1、标准广播
标准广播是一种完全异步执行的广播,在广播发出之后,所有的BroadcastReceiver几乎在同一时刻收到这个广播消息,它们之间没有先后顺序,这种广播的效率较高,并且不能被拦截。
1.2、有序广播
有序广播是一种完全同步的广播,在广播发出后只能有一个BroadcastReceiver能接收到这个广播消息,当这个BroadcastReceiver中的逻辑执行完毕后,广播才能继续向下传递。所以这个广播是有顺序的,所以这种广播也是可以被拦截的,如果被拦截了后面的BroadCastReceiver则不能收到广播消息了。
2、系统广播的注册
广播的注册分为动态注册和静态注册。
2.1、动态注册系统广播
- 1、创建BroadCastReceiver的子类,在
onReceive()
编写相应的逻辑。
class TimeChangeReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
context?.let {
showToast(it, "收到了时间变化的广播")
}
}
}
- 2、通过
registerReceiver()
注册广播监听 - 3、在页面关闭时记得通过
unregisterReceiver()
注销广播监听,否则会因广播持有Activity引用导致内存泄露。
class ReceiverActivity : AppCompatActivity() {
var receiver:TimeChangeReceiver?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_receiver)
btn_regist.setOnClickListener {
val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_TIME_TICK)
receiver = TimeChangeReceiver()
registerReceiver(receiver, intentFilter)
}
}
override fun onDestroy() {
super.onDestroy()
receiver?.let {
unregisterReceiver(it)
}
}
}
这样我们就注册系统时间变化的广播,在时间变化时广播了。
2.2、静态注册系统广播
动态注册广播可以很方便的注册和注销广播,但是这都是基于程序启动的状态下进行的,那么能不能在程序未启动时就能接收到广播呢?这就用到了静态注册广播,但是有很多恶意应用通过静态注册的方法监听系统的广播,然后频繁的唤醒应用导致用户手机的性能和电量,在Android8.0后,所有隐式广播都不能通过静态注册了,隐式广播是指没有指定那个应用程序接收广播。而大多数系统广播都是隐式广播,但是也有少数的特殊广播仍然能允许通过静态注册的方法注册,比如:开机广播,下面我们就通过静态注册的方法注册系统开机的广播。
- 1、创建BootcastReceiver继承BroadCastReceiver
class BootReceiver:BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
context?.let {
Toast.makeText(context,"开启",Toast.LENGTH_LONG).show()
}
}
}
- 2、在Manifest中注册receiver
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application>
<receiver android:name=".receiver.BootReceiver"
android:exported="true"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
这样就完成了开机启动的静态广播的注册,不过为了保护用户的安全和隐私,需要对权限进行声明,在接收系统开启广播需要在Manifest中配置权限。
另外需要注意,在onReceive()
不能执行耗时操作,onReceive()
默认是在主线程中,进行耗时会阻塞主线程,如果非要执行耗时操作最好开启一个服务在服务中进行耗时操作,不建议开启线程来处理耗时操作,因为BroadCastReceiver的生命周期很短,可能在子线程结束前BroadCastReceiver已经退出,如果当BroadCastReceiver所在的进程结束,虽然该进程中可能有用户启动的新线程,但是由于该进程内没有活动的组件,系统会在内存紧张的时候,优先结束掉该进程,这就会导致BroadCastReceiver启动的子线程不能执行完。
3、自定义广播的动态注册和静态注册
自定义广播和系统广播的区别就在于,广播消息的发送是我们手动触发的,而系统广播是由系统触发的。下面我们简单看下使用过程。
3.1、动态注册自定义广播
代码如下:
class ReceiverActivity : AppCompatActivity() {
var receiver:DynamicCustomReceiver?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_receiver)
btn_regist.setOnClickListener {
val intentFilter = IntentFilter()
intentFilter.addAction(DynamicCustomReceiver::class.java.name)
receiver = DynamicCustomReceiver()
registerReceiver(receiver, intentFilter)
}
btn_send_broad.setOnClickListener {
val intent=Intent(DynamicCustomReceiver::class.java.name)
sendBroadcast(intent)
}
}
override fun onDestroy() {
super.onDestroy()
receiver?.let {
unregisterReceiver(it)
}
}
}
DynamicCustomReceiver
class DynamicCustomReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
context?.let {
showToast(it, "自定义广播动态注册")
}
}
}
3.2、静态注册自定义广播
代码如下:
AndroidManifest中注册
<application>
<receiver android:name=".receiver.StaticCustomReceiver">
<intent-filter>
<action android:name="com.example.abu.listview.StaticCustomReceiver"/>
</intent-filter>
</receiver>
</application>
创建广播
class StaticCustomReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
context?.let {
showToast(it, "自定义广播静态注册")
}
}
}
发送广播
val intent = Intent("com.example.abu.listview.StaticCustomReceiver")
intent.setPackage(packageName)
sendBroadcast(intent)
由于自8.0以后隐式广播不能进行静态注册了,所以这里通过setPackage()
指定应用程序响应广播。
4、有序广播
前面我们学习标准广播的发送,下面看下有序广播是如何使用。
4.1、静态注册有序广播
AndroidManifest中注册有序广播
<receiver android:name=".receiver.StaticCustomReceiver">
<intent-filter android:priority="100">
<action android:name="com.example.abu.listview.StaticCustomReceiver"/>
</intent-filter>
</receiver>
<receiver android:name=".receiver.StaticBroadcastReceiver">
<intent-filter android:priority="90">
<action android:name="com.example.abu.listview.StaticCustomReceiver"/>
</intent-filter>
</receiver>
可以看到我们给StaticCustomReceiver
和StaticBroadcastReceiver
通过android:priority
设置接收广播的优先级
创建StaticCustomReceiver
和StaticBroadcastReceiver
class StaticBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
context?.let {
showToast(it, "另一个静态注册自定义广播")
}
}
}
class StaticCustomReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
context?.let {
showToast(it, "自定义广播静态注册")
}
abortBroadcast()
}
}
可以看到我们可以在abortBroadcast()
来拦截优先级低的广播,使得优先级低的广播无法收到广播消息
发送广播
val intent = Intent("com.example.abu.listview.StaticCustomReceiver")
intent.setPackage(packageName)
sendOrderedBroadcast(intent,null)
sendOrderedBroadcast(intent,null)
发送了一个有序广播,第二个参数是权限相关的字符串传入null即可
上面是静态注册有序广播的过程,和动态注册有序广播的过程类似,区别就在于静态注册广播我们在AndroidManifest中指定优先级,动态注册我们在注册时通过intentFilter.priority=100
来设定广播的优先级。
网友评论