广播分为标准广播和有序广播。
1.1、标准广播标准广播是一种完全异步执行的广播,在广播发出之后,所有的BroadcastReceiver几乎在同一时刻收到这个广播消息,它们之间没有先后顺序,这种广播的效率较高,并且不能被拦截。
1.2、有序广播有序广播是一种完全同步的广播,在广播发出后只能有一个BroadcastReceiver能接收到这个广播消息,当这个BroadcastReceiver中的逻辑执行完毕后,广播才能继续向下传递。所以这个广播是有顺序的,所以这种广播也是可以被拦截的,如果被拦截了后面的BroadCastReceiver则不能收到广播消息了。
2、系统广播的注册广播的注册分为动态注册和静态注册。
2.1、动态注册系统广播1、创建BroadCastReceiver的子类,在onReceive()
编写相应的逻辑。class TimeChangeReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { context?.let { showToast(it, "收到了时间变化的广播") } }}
2、通过registerReceiver()
注册广播监听3、在页面关闭时记得通过unregisterReceiver()
注销广播监听,否则会因广播持有Activity引用导致内存泄露。class ReceiverActivity : AppCompatActivity() { var receiver:TimeChangeReceiver?=null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_receiver) btn_regist.setOnClickListener { val intentFilter = IntentFilter() intentFilter.addAction(Intent.ACTION_TIME_TICK) receiver = TimeChangeReceiver() registerReceiver(receiver, intentFilter) } } override fun onDestroy() { super.onDestroy() receiver?.let { unregisterReceiver(it) } }}
这样我们就注册系统时间变化的广播,在时间变化时广播了。
2.2、静态注册系统广播动态注册广播可以很方便的注册和注销广播,但是这都是基于程序启动的状态下进行的,那么能不能在程序未启动时就能接收到广播呢?这就用到了静态注册广播,但是有很多恶意应用通过静态注册的方法监听系统的广播,然后频繁的唤醒应用导致用户手机的性能和电量,在Android8.0后,所有隐式广播都不能通过静态注册了,隐式广播是指没有指定那个应用程序接收广播。而大多数系统广播都是隐式广播,但是也有少数的特殊广播仍然能允许通过静态注册的方法注册,比如:开机广播,下面我们就通过静态注册的方法注册系统开机的广播。
1、创建BootcastReceiver继承BroadCastReceiverclass BootReceiver:BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { context?.let { Toast.makeText(context,"开启",Toast.LENGTH_LONG).show() } }}
2、在Manifest中注册receiver <uses-permission android:/> <application> <receiver android: android:exported="true" android:enabled="true"> <intent-filter> <action android:/> </intent-filter> </receiver> </application>
这样就完成了开机启动的静态广播的注册,不过为了保护用户的安全和隐私,需要对权限进行声明,在接收系统开启广播需要在Manifest中配置权限。
另外需要注意,在onReceive()
不能执行耗时操作,onReceive()
默认是在主线程中,进行耗时会阻塞主线程,如果非要执行耗时操作最好开启一个服务在服务中进行耗时操作,不建议开启线程来处理耗时操作,因为BroadCastReceiver的生命周期很短,可能在子线程结束前BroadCastReceiver已经退出,如果当BroadCastReceiver所在的进程结束,虽然该进程中可能有用户启动的新线程,但是由于该进程内没有活动的组件,系统会在内存紧张的时候,优先结束掉该进程,这就会导致BroadCastReceiver启动的子线程不能执行完。
自定义广播和系统广播的区别就在于,广播消息的发送是我们手动触发的,而系统广播是由系统触发的。下面我们简单看下使用过程。
3.1、动态注册自定义广播代码如下:
class ReceiverActivity : AppCompatActivity() { var receiver:DynamicCustomReceiver?=null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_receiver) btn_regist.setOnClickListener { val intentFilter = IntentFilter() intentFilter.addAction(DynamicCustomReceiver::class.java.name) receiver = DynamicCustomReceiver() registerReceiver(receiver, intentFilter) } btn_send_broad.setOnClickListener { val intent=Intent(Dynami(中文邮件格式:邮件的主题是为了让收件人看到邮件之后对该邮件有个大体了解,确定邮件的紧急、重要程度、有效、有用性的;所以在写主题的时候最主要的突出 什么事、重要程度等关键信息;可以按照以下方式和思路去写:格式:修饰词+邮件内容+时间+发件人。如果有必要的话还可以在主题上加上紧急程度和邮件的主体内容,清晰明了。)cCustomReceiver::class.java.name) sendBroadcast(intent) } } override fun onDestroy() { super.onDestroy() receiver?.let { unregisterReceiver(it) } }}
DynamicCustomReceiver
class DynamicCustomReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { context?.let { showToast(it, "自定义广播动态注册") }