BroadcastReceiver
- 标准广播:完全异步执行,在发出后所有的BroadcastRecevier几乎会在同一时刻收到这条广播消息。效率比较高,无法被截断。
- 有序广播:同步执行,在发出后同一时刻只有一个BroadcastReceiver能够收到这条广播消息,当逻辑执行完毕时才会继续传递。前面的可以截断正在传递的广播,这样后面的就不能收到了。
接受系统广播
有广播发出时,注册相应的BroadcasetReceiver就能够收到该广播,并可以在内部进行逻辑处理。注册方法有两种:
- 动态注册:在代码中注册,只有在程序启动之后才能接收广播。
- 静态注册:在AndroidManifest中注册,可以在程序未启动时接收广播。
动态注册监听时间变化
新建一个类继承自BroadcastReceiver,并重写onReceive,当有广播到来时就会执行onReceive方法。
inner class TimeChangeReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context, "Time has changed", Toast.LENGTH_SHORT).show()
}
}
新建变量lateinit var timeChangeReceiver: TimeChangeReceiver
在onCreate中添加以下代码
val intentFilter = IntentFilter()
intentFilter.addAction("android.intent.action.TIME_TICK")
timeChangeReceiver = TimeChangeReceiver()
registerReceiver(timeChangeReceiver, intentFilter)
创建一个IntentFilter实例,添加一个值为android.intent.action.TIME_TICK的action,因为当系统时间变化时会发出一条相同值的广播。
动态注册一定要取消注册才行,可以在onDestroy中调用unregisterReceiver()来实现。
unregisterReceiver(timeChangeReceiver)
静态注册实现开机启动
新建一个类继承BroadcastReceiver并重写onReceive方法。
在AndroidManifest中添加以下代码
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.broadcasttest">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
...
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
...
</application>
Android系统规定需要进行敏感操作时,必须进行权限声明,所以声明了android.permission.RECEIVE_BOOT权限。
发送自定义广播
发送标准广播
新建一个类继承BroadcastReceiver并重写onReceive方法。然后在AndroidManifest中注册如:
<receiver
android:name=".AnotherBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.broadcasttest.MY_BROADCAST" />
</intent-filter>
</receiver>
然后使用以下代码发送
val intent = Intent("com.example.broadcasttest.MY_BROADCAST")
intent.setPackage(packageName)
sendBroadcast(intent)
由于Android8.0后,静态注册的BroadcastReceiver无法接受隐式广播,而默认情况下的自定义广播都是隐式广播。因此要调用setPackage指定这条广播时发送给哪个应用程序的,从而让它变成一条显式广播。
发送有序广播
只需要改动sendBroadcast(intent)
为sendOrderedBroadcast(intent, null)
第二个参数是一个与权限相关的字符串。
可以在AndroidManifest中设置优先级
<intent-filter android:priority="100">
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
截断传递只需要调用abortBroadcast()。