前言
上篇文章复习总结了 Service 的相关知识,现在开始复习 BroadcastReceiver。BroadcastReceiver 能够接受系统或者其他 App 发来的特定广播,本文先从广播的发送开始。
两种发送方式
sendOrderdBroadcast(Intent, String)
发送有序广播,优先级(通过 android:priority
或者 setPriority
设置)高的 BroadcastReceiver 会被优先收到(如果优先级相同,则动态注册的优先级高于静态注册的),其可以改变广播传递的内容或者直接中止该广播,通过调用 abortBroadcast
。
sendBroadcast(Intent, String)
发送无序广播,忽略广播接受者的优先级(因此无法被中止),所有广播接受者按照一种不确定的顺序接收到。
两种注册方式
静态注册
只需要新建一个类继承 BroadcastReceiver ,然后在清单文件 application 节点下,配置 receiver 节点即可,例如下面这段代码就配置了一个可用于接受飞行模式开关状态的 BroadcastReceiver。
<receiver android:name=".MyBroadcastReceiver"> |
静态注册的 BroadcastReceiver 只要应用程序进程没被杀死就能接受到对应的广播,但是其没法接受某些系统的广播例如屏幕打开关闭、电量改变等。
动态注册
动态注册首先新建一个类继承 BroadcastReceiver 的实例,然后再创建一个 IntentFilter 实例设置该BroadcastReceiver 关注哪几种广播,最后调用 registerReceiver
注册广播,例如以下代码就动态注册了一个BroadcastReceiver。
fun registerBroadcastReceiver() { |
动态注册可以接受到静态注册无法接收到广播例如屏幕打开关闭、电量改变等,此外动态注册的广播我们在用完以后应该调用 unregisterReceiver
解除注册,虽然系统也会帮我们解除,但是会打印错误。
使用 BroadcastReceiver 的注意点
虽然系统规定 BroadcastReceiver 的 onReceive
最多执行 10 秒,但是由于该方法运行于主线程所以其实超过5秒就会 ANR,如果我们要在 onReceiver 执行耗时任务里面就会想到开一个线程执行,但是当 onReceive
调用完毕后系统就会去销毁该实例,这样那个新建的线程优先级就非常低了很容易被杀死,导致达不到我们要效果。有以下两种方法可以用于解决这种情况。
- 通过在
onReceive
中调用goAsync
获得 PendingResult 对象以后再开启子线程,在执行结束时调用PendingResult.finish,不过只能运行 10 秒。 - 通过在
onReceive
中启动服务(比如IntentService)运行耗时任务。
本地广播和粘性广播
这两种广播都可以使用开源库 EventBus 代替。