广播机制
Android中的广播主要可以分为两种类型:标准广播和有序广播。
- 标准广播(normal broadcasts)是一种完全异步执行的广播,在广播发出之后,所有的BroadcastReceiver几乎会在同一时刻收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5k5TwJIT-1660658244900)(images/2022-08-16-20-08-21.png)]
*有序广播(ordered broadcasts)则是一种同步执行的广播,在广播发出之后,同一时刻只会有一个BroadcastReceiver能够收到这条广播消息,当这个BroadcastReceiver中的逻辑执行完毕后,广播才会继续传递。所以此时的BroadcastReceiver是有先后顺序的,优先级高的BroadcastReceiver就可以先收到广播消息,并且前面的BroadcastReceiver还可以截断正在传递的广播,这样后面的BroadcastReceiver就无法收到广播消息了。
1.接收系统广播
需要先注册BroadcastReceiver,这样当有相应的广播发出时,相应的BroadcastReceiver就能够收到该广播,并可以在内部进行逻辑处理。
BroadcastReceiver的方式一般有两种:
- 1.动态注册:在代码中注册
- 2.静态注册:在AndroidManifest.xml中注册。
1.动态注册监听时间变化
class MainActivity : AppCompatActivity() {
lateinit var timeChangeReceiver: TimeChangeReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intentFilter = IntentFilter()//创建了一个IntentFilter的实例
intentFilter.addAction("android.intent.action.TIME_TICK")//接下来想要监听什么广播就可以.addAction,这个是时间变化的广播
timeChangeReceiver = TimeChangeReceiver()//创建接收到广播后的实现逻辑实例
registerReceiver(timeChangeReceiver, intentFilter)
//需要将实现逻辑的实例和注册监听的广播进行注册
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(timeChangeReceiver)//注册完成后一定要取消注册
}
inner class TimeChangeReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context, "Time has changed", Toast.LENGTH_SHORT).show()
}
}
}
如果你想查看完整的系统广播列表,可以到如下的路径中去查看:
<Android SDK>/platforms/<任意android api版本>/data/broadcast_actions.txt
特点:
- 1.灵活,动态注册的BroadcastReceiver可以自由地控制注册与注销
- 2.局限,因为定义在onCreate()方法中,因此必须在程序启动以后才能接收广播
2.静态注册实现开机启动
创建广播类:
- 1.右击com.example.broadcasttest包→New→Other→Broadcast Receiver
- 2.勾选Exported:表示是否允许这个BroadcastReceiver接收本程序以外的广播;勾选Enabled属性:表示是否启动BroadcastReceiver(这样在AndroidManifest.xml文件中就可以完成注册了,静态的BroadcastReceiver一定要在这个文件中注册才可以使用)
- 3.在类中修改实现逻辑
- 4.在AndroidManifest.xml文件中的中注册要监听的广播
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />//注册启动的广播
</intent-filter>
</receiver>
note:
在进行注册的时候要先进行权限声明,否则程序会直接崩溃
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />//开机启动权限声明
ps:
不要在onReceive()方法中添加过多的逻辑或者进行任何的耗时操作,因为BroadcastReceiver中是不允许开启线程的,当onReceive()方法运行了较长时间而没有结束时,程序就会出现错误。
2.发送自定义广播
1.发送标准广播
- 1.和上边一样先定义一个类来做接收广播后的逻辑动作
- 2.AndroidManifest.xml中对这个BroadcastReceiver进行修改:
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
//这里让MyBroadcastReceiver接收一条值为com.example.broadcasttest.MY_BROADCAST的广播,因此待会儿在发送广播的时候,我们就需要发出这样的一条广播。
</intent-filter>
</receiver>
- 3.修改activity_main.xml中的代码定义一个按钮(或其他)来作为发送广播的触发点。
button.setOnClickListener {
val intent = Intent("com.example.broadcasttest.MY_BROADCAST")
intent.setPackage(packageName)
sendBroadcast(intent)
}
调用Intent的setPackage()方法,并传入当前应用程序的包名。packageName是getPackageName()的语法糖写法,用于获取当前应用程序的包名。最后调用sendBroadcast()方法将广播发送出去.
**note:**静态注册的BroadcastReceiver是无法接收隐式广播的,而默认情况下发出的自定义广播都是隐式广播。因此这里一定要调用setPackage()方法,指定这条广播是发送给哪个应用程序的,从而让它变成一条显式广播,否则静态注册的BroadcastReceiver将
无法接收到这条广播。
2.发送有序广播
- 1.多注册一个BroadcastReceiver用来体现先后和截止功能
在onReceiver中添加:abortBroadcast()方法,就表示将这条广播截断,后面的BroadcastReceiver将无法再接收到这条广播。 - 2.在AndroidManifest.xml中对这个BroadcastReceiver进行修改:
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="100">//指定这个广播接收器的优先级
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>
- 3.修改MainActiviy中的广播发出函数为
sendOrderedBroadcast(intent, null)
第一个参数仍然是Intent;第二个参数是一个与权限相关的字符串,这里传入null就行了。
3.广播发射总结
动态:(可以一直在MainAcitivity中)注册一个内部类广播接收器来执行接收广播后的动作;定义一个IntentFileter的实例,并添加动作(也就是可以接收到的广播);定义一个广播接收器,并对广播接收器和注册可以接收的广播进行注册;最后取消注册(可以在onDestory函数中)
广播接收器来执行接收广播后的动作;定义一个IntentFileter的实例,并添加动作(也就是可以接收到的广播);定义一个广播接收器,并对广播接收器和注册可以接收的广播进行注册;最后取消注册(可以在onDestory函数中)
静态:大致就是先编写一个广播接收器,用来执行接收到广播后的动作(也可以在这个接收器这里选截断广播);然后在AndroidMainifest.xml中进行注册接收什么广播(可以在这个时候指定接收器优先级,确定哪个接收器先收到广播);然后定义发射广播的事件(有序,无序)等。