学习Android之广播机制
广播机制简介
Android中的广播机制十分灵活,每个应用程序都可以对自己感兴趣的广播进行注册,这样该程序就只会收到自己所关心的广播内容,这些广播可能是来自于系统的,也可能是来自于其他应用程序的。
Android提供了一套完整的API,允许应用程序自由地发送和接收广播。
发送广播可以借助Intent,接收广播则需要借助BroadcastReceiver。
广播的类型
标准广播和有序广播。
标准广播:一种完全异步执行的广播,发出后,所有的BroadcastReceiver几乎同时收到这条广播消息,没有先后顺序。效率高,但无法被截断。
有序广播:一种异步执行的广播,发出后,同一时刻只能有一个BroadcastReceiver收到消息,当这个BroadcastReceiver处理完后,广播才能继续传递下去,有先后顺序。优先级高的BroadcastReceiver会先收到广播消息。并且还可以截断正在传递的广播。
接收系统广播
Android内置了很多系统级别的广播,比如手机开机,电量变化等等。想要接收他们的广播,就要用到BroadcastReceiver。
动态注册监听时间变化
注册方法一般有两种:在代码中注册(动态注册)和在AndroidManifest.xml中注册(静态注册)。
那么如何创建一个BroadcastReceiver呢?
只需要新建一个类,继承自BroadcastReceiver,并重写父类的onReceive()方法即可。当有广播来时,onReceive()方法就会执行。
例子:动态注册一个监听时间变化的程序。
在MainActivity中定义了一个内部类TimeChangeReceiver,继承自BroadcastReceiver,重写了onReceive()方法。
inner class TimeChangeReceiver : BroadcastReceiver() { override fun onReceive(p0: Context?, p1: Intent?) { TODO("Not yet implemented") } }
在onCreate()方法,先创建一个IntentFilter的实例,给它添加一个值为android.intent.action.TIME_TICK的action。因为系统时间发生变化时,系统发出的正是一条值为android.intent.action.TIME_TICK的广播。也就是说,想要监听什么广播,就在这里添加相应的action。
接下来创建一个TimeChangeReceiver的实例,然后调用registerReceiver()方法进行注册,将TimeChangeReceiver的实例和IntentFilter的实例都传了进去,这样TimeChangeReceiver就会收到所有值为android.intent.action.TIME_TICK的广播,也就实现了监听系统时间变化的功能。
val intentFilter = IntentFilter() intentFilter.addAction("android.intent.action.TIME_TICK") timeChangeReceiver = TimeChangeReceiver() registerReceiver(timeChangeReceiver,intentFilter)
这里需要将timeChangeReceiver声明为全局变量,需要用到延迟初始化:
lateinit var timeChangeReceiver: TimeChangeReceiver
最后记得,动态注册的BroadcastReceiver一定要取消注册才行,在onDestory()中调用unregisterReceiver()方法即可。
unregisterReceiver(timeChangeReceiver)
最后运行程序,系统每隔一分钟就会发出一条android.intent.action.TIME_TICK的广播。
想要查看完整的系统广播列表,前往如下路径:
<Android SDK>/platforms/<任意android api版本>/data/broadcast_actions.txt
静态注册实现开机启动
动态注册的可以自由地控制注册与注销,在灵活性方面有很大的优势。但是有一个缺点就是必须在程序启动之后才能接收广播。因为实在onCreate()中注册的。
静态注册则能实现程序未启动的情况下也能接收广播。(简述一下原理,在安装应用的时候,系统会启动PackageManagerService管理服务,这个服务对AndroidManifest进行解析,从而得到应用程序的相关信息,比如service,activity,Broadcast等等。)
实现开机广播的action值为android.intent.action.BOOT_COMPLETED。
首先我们需要新建一个广播类,可以通过New->Other->Broadcast新建。新建时有两个属性:Exported属性表示是否允许这个BroadcastReceiver接收本程序以外的广播,Enabled属性表示是否启用这个BroadcastReceiver。都勾选上。
然后在onReceive()中编写逻辑即可。
另外,静态的BroadcastReceiver需要在AndroidManifest.xml文件中注册。不过新建时自动注册了。
<receiver android:name=".BootCompleteReceiver" android:enabled="true" android:exported="true"></receiver>
同时,需要在<receiver>标签中添加了一个<intent-filter>标签,在里面声明相应的action。
<receiver android:name=".BootCompleteReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver>
最后再进行权限声明。
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
发送自定义广播
发送标准广播
1. 创建广播接收者:在发送广播之前,需要先定义一个BroadcastReceiver来准备接收此广播。新建一个MyBroadcastReceiver,并在onReceive()方法中编写逻辑。
2. 添加广播接收者需要接收的action:在AndroidManifest对这个BroadcastReceiver修改。将action设为com.example.broadcasttest.MY_BROADCAST。所以等会就会发送这样一条广播。
3. 发送广播:在MainActivity中的添加按钮点击事件,里面编写广播发送代码。
val intent = Intent("com.example.broadcasttest.MY_BROADCAST")
intent.setPackage(packageName)
sendBroadcast(intent)
为什么会用到setPackage()方法:在Android 8.0系统之后,静态注册的BroadcastReceiver是无法接收隐式广播的,而默认情况下我们发出的自定义广播恰恰都是隐式广播。因此这里一定要调用setPackage()方法,指定这条广播是发送给哪个应用程序的,从而让它变成一条显式广播,否则静态注册的BroadcastReceiver将无法接收到这条广播。
发送有序广播
有序广播是可以被截断的。发送有序广播只需要改动一行代码。
sendOrderedBroadcast(intent,null)
此方法接收两个参数:第一个Intent,第二个是一个与权限相关的字符串,这里传入null就行了。
这个时候的BroadcastReceiver是有先后顺序的,而且前面的BroadcastReceiver还可以将广播截断,以阻止其继续传播。
设定先后顺序是在注册的时候进行设定,修改AndroidManifest.xml中的代码,如下所示:
<intent-filter android:priority="1"> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter>
通过android:priority属性设置优先级,值越大优先级越高。
然后在onReceive()方法中调用abortBroadcast()方法,表示将这条广播截断,后面的BroadcastReceiver将无法再接收到这条广播。
override fun onReceive(context: Context, intent: Intent) { TODO("BootCompleteReceiver.onReceive() is not implemented") abortBroadcast() }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】