Android中Service机制
基础
广播的类型:标准广播(高效,无法截断)、有序广播(同步执行,可以截断,有先后顺序)
接收系统广播
动态注册监听系统广播
BroadcastReceiver的创建方法:新建一个类,让它继承自BroadcastReceiver,并重写父类的onReceive()方法。
书上的示例,监听系统时间变化的广播,显示通知。
class MainActivity : AppCompatActivity() {
lateinit var timeChangeReceiver: TimeChangeReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//过滤要监听的广播:系统时间发生变化发出的“android.intent.action.TIME_TICK”
val intentFilter = IntentFilter()
intentFilter.addAction("android.intent.action.TIME_TICK")
//创建TimeChangeReceiver的实例,并调用registerReceiver注册
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()
}
}
}
//targetApi 31测试是可以这样写的
静态注册实现开机启动
喜闻乐见的被滥用的功能,频繁啊唤醒的恶意App,即使可能离不来,笑。
用AndroidStudio
创建静态BroadcastReceiver
,以及会自动在AndroidManifest中注册。
在<receiver>
标签中添加<intent-filter>
声明对应action,并且声明接收开机广播的权限。
<?xml version="1.0" encoding="utf-8"?>
<manifest
...>
<!--接收开机广播毕竟是个有点敏感的权限呢-->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
<application
...>
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<!--声明对应action-->
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
...
</application>
</manifest>
实体机和虚拟机盯着看了半天没看到Toast消息,不知道为什么,不过加了条log的输出,也算是看到了,真的开机自启动了呢!
自定义广播
发送标准广播
class MainActivity : AppCompatActivity() {
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
val intent = Intent("com.example.broadcasttest.MY_BROADCAST")
//指定这条广播是发送给哪个应用程序的,让它变成一条显式广播
intent.setPackage(packageName)
sendBroadcast(intent)
}
...
}
...
}
接收广播的BroadcastReceiver
,和前面的写法是一样的
广播是使用Intent来发送的,因此你还可以在Intent中携带一些数据传递给相应的BroadcastReceiver
发送有序广播
有序广播的发送
将sendBroadcast(intent)
改变为sendOrderedBroadcast(intent, null)
,第二个参数是一个与权限相关的字符串。
有序广播的接收
...
<receiver
android:name=".MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<!--这里的priority为BroadcastReceiver设置了优先级,优先级高的先收到广播-->
<intent-filter android:priority="100">
<action android:name="com.example.broadcasttest.MY_BROADCAST"/>
</intent-filter>
</receiver>
...
有序广播的截断
class MyBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context, "received in MyBroadcastReceiver",
Toast.LENGTH_SHORT).show()
abortBroadcast()//截断这条广播
}
}
广播的最佳实践
要在onReceive()
方法中弹出一个对话框,需要动态注册的BroadcastReceiver
,可以在BaseActivity
中注册,所有Activity都继承自BaseActivity。
将注册和取消注册放在onResume()
,onPause()
的生存周期,就能做到只保证栈顶的Activity才能接收这条广播。
open class BaseActivity : AppCompatActivity() {
...
override fun onResume() {
super.onResume()
val intentFilter = IntentFilter()
intentFilter.addAction("com.example.broadcastbestpractice.FORCE_OFFLINE")
receiver = ForceOfflineReceiver()
//注册Receiver
registerReceiver(receiver, intentFilter)
}
override fun onPause() {
super.onPause()
//取消注册
unregisterReceiver(receiver)
}
...
}
标签:...,20240203,fun,广播,intent,override,BroadcastReceiver
From: https://www.cnblogs.com/sugar-refinery/p/18007245