第 6 章
全局大喇叭,详解广播机制
6.1 广播机制简介
广播分为两种类型:
- 标准广播(Normal broadcasts): 完全异步执行。发出广播后,所有BroadcastReceiver立刻同时收到广播消息;
- 有序广播 (Ordered broadcasts):同步执行广播。发出广播后,同一时刻只有一个BroadcastReceiver能够收到,且一个BroadcastReceiver中的逻辑执行完毕之后,广播才会继续传递。因此前面的BroadcastReceiver可以拦截广播消息。
6.2 接收系统广播
注册BroadcastReceiver有两种方式:
- 动态注册:在代码中注册;
- 静态注册:在AndroidManifest.xml中注册;
创建BroadcastReceiver:新建一个类,继承自BroadcastReceiver,并重写父类的onReceive( )
方法就可以了。
6.2.1 动态注册:监听时间变化
- 监听什么广播?
intentFilter.addAction("android.intent.action.TIME_TICK")
- 监听到广播之后要做什么?
inner class TimeChangeReceiver: BroadcastReceiver()
- 最后:
registerReceiver(timeChangeReceiver, intentFilter)
- 别忘了取消监听:
unregisterReceiver(timeChangeReceiver)
class MainActivity : AppCompatActivity() {
private lateinit var timeChangeReceiver : TimeChangeReceiver
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val intentFilter = IntentFilter()
intentFilter.addAction("android.intent.action.TIME_TICK") // 收到什么广播
timeChangeReceiver = TimeChangeReceiver()
registerReceiver(timeChangeReceiver, intentFilter)
}
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(timeChangeReceiver) // 动态注册的BroadcastReceiver一定要取消注册才行
}
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/boradcast_actions.txt
6.2.2 静态注册:实现开机启动
动态注册可以自由控制注册与注销,但是只能在程序启动后才能接收广播,因为注册是在onCreate( )
中的。此时静态注册的优点就显现出来了。
- 创建BootCompleteReceiver类,编写
onReceive( )
方法,收到广播之后执行什么动作; - 在AndroidManifest中注册静态的BroadcastReceiver,不过这步已经由AS自动完成了(<receiver>);
- 添加权限;
- 添加
<intent-filter>
但一开始并没有看到弹窗,后来发现是系统禁止了应用的后台弹窗权限。如果遇到问题怀疑是权限导致的bug,并且在设置里没找到安装的app,可以使用以下代码快速跳转至权限管理页面:
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) val uri = Uri.fromParts("package", packageName, null) intent.data = uri startActivity(intent)
6.3 发送自定义广播
6.3.1 发送标准广播
val button: Button = findViewById(R.id.button)
button.setOnClickListener {
val intent = Intent("com.example.boradcasttest.MY_BROADCAST")
intent.setPackage(packageName)
// 由于静态注册的BoradcastReceiver是无法收到隐式广播的,
// 因此必须指定当前app的包名,指定这条广播是发送给哪个应用程序的,从而让它变成显式广播。
sendBroadcast(intent)
}
在调试的时候别忘了注册一个接收该广播的BoradcastReceiver。
6.3.2 发送有序广播
发送有序广播:sendOrderedBroadcast(intent, null)
,第二个参数是与权限有关的字符串;
设置优先级:在AndroidManifest中,在intent-filter
后添加android:priority="100"
;
截断广播:abortBroadcast()
6.4 最佳实践:强制下线功能
- 需要关闭所有Activity:使用第3章的思路。创建ActivityCollector管理所有Activity,再创建BaseActivity作为父类;
- 创建LoginActivity;
- 修改MainActivity,加一个强制下线的按钮,就是发送一条FORCE_OFFLINE的广播;
- 如何接收这条广播?只需要在BaseActivity中注册一个BoradcastReceiver就可以了。
6.5 Kotlin课堂:高阶函数详解
看不懂思密达
6.6 Git Bash
- 查看Git用户名/邮箱:
git config --global user.name/email
- 创建代码仓库:进入目录,再输入
git init
- 查看所有文件:
ls -al
- 添加想要提交的代码:
git add .
(所有文件) - 提交代码:
git commit -m "hahaha"