广播机制

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中进行注册接收什么广播(可以在这个时候指定接收器优先级,确定哪个接收器先收到广播);然后定义发射广播的事件(有序,无序)等。