广播机制
用BroadcastReceiver接收。分两种类型:
- 标准广播
完全异步广播,接收者同步收到,无法阻拦,传播效率高。 - 有序广播
同步广播,一次只能有一个接收者,优先级越高,越早接收,接收者可以阻断传播。
注册方法
动态注册
在代码注册静态注册
在AndroidManifest.xml注册
动态注册
动态注册一定要取消注册,可以在onDestory()取消。
代码如下所示。
class MainActivity : AppCompatActivity()
{
lateinit var timeChange: TimeChange
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
timeChange = TimeChange()
val intentFilter = IntentFilter().apply {
// 监听的事件
addAction("android.intent.action.TIME_TICK")
}
// 注册
registerReceiver(timeChange, intentFilter)
}
override fun onDestroy()
{
super.onDestroy()
// 取消注册
unregisterReceiver(timeChange)
}
inner class TimeChange : BroadcastReceiver()
{
// 不支持线程,过长时间运行会报错
override fun onReceive(p0: Context?, p1: Intent?)
{
Toast.makeText(this@MainActivity, "时间改变", Toast.LENGTH_SHORT).show()
}
}
}
静态注册
动态注册只有在程序启动的时候才能接收,而在android 8.0以后,所有的隐式广播都不允许使用静态注册方式接收了。
隐式广播:没有具体指发送给某程序的广播,大多数系统广播属于隐式广播。但譬如开机启动广播还是静态注册。
class MainActivity : AppCompatActivity()
{
// 必须是静态
class BootComplete : BroadcastReceiver()
{
override fun onReceive(context: Context?, p1: Intent?)
{
Toast.makeText(context, "开机", Toast.LENGTH_SHORT).show()
}
}
}
申请权限以及注册receiver
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application ...>
<receiver
android:name=".MainActivity$BootComplete"
android:enabled="true"
android:exported="true"/>
<activity
android:name=".MainActivity">
...
</activity>
</application>
自定义广播
- 自定义接收器
- 在AndroidManifest添加
receiver
标签,并补全。 - 写
sendBroadcast
这里定义发送广播为this.is.my.br
class MainActivity : AppCompatActivity()
{
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
val button = Button(this)
button.setOnClickListener {
Intent("this.is.my.br").run {
// 8.0之后,无法接收隐式广播,默认自定义都是隐式,
// 所以要调用这个发送给指定应用程序,从而显式化
setPackage(packageName)
// 可以此法传输数据
putExtra("text", "this is broadcast data")
sendBroadcast(this)
}
}
setContentView(button)
}
// 必须是静态
class MyBroadcastReceiver : BroadcastReceiver()
{
override fun onReceive(context: Context?, pIntent: Intent?)
{
val res = pIntent?.getStringExtra("text") ?: "无数据"
Toast.makeText(context, "My Broadcast Receiver :$res", Toast.LENGTH_SHORT).show()
}
}
}
receiver标签加在application里,指定MainActivity$MyBroadcastReceiver
为接收者,并写入intent-filter的响应活动是this.is.my.br
<receiver
android:name=".MainActivity$MyBroadcastReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="this.is.my.br"/>
</intent-filter>
</receiver>
发送有序广播
有序广播继承了标准广播的写法,改的如下:
- sendBroadcas() 改为
sendOrderedBroadcast()
,如无必要,与权限有关的第二参数可填null - 设定先后顺序:在AndroidManifest.xml的
receiver
标签下的intent-filter
加入优先级 - 截断方法:abortBroadcast()
<receiver ...>
<intent-filter android:priority="100">
<action android:name="this.is.my.br"/>
</intent-filter>
</receiver>
class MainActivity : AppCompatActivity()
{
private fun sendMyBroadcast()
{
Intent("this.is.my.br").run {
// 8.0之后,无法接收隐式广播,默认自定义都是隐式,
// 所以要调用这个发送给指定应用程序,从而显式化
setPackage(packageName)
// 可以此法传输数据
putExtra("text", "this is broadcast data")
// sendBroadcast(this)
sendOrderedBroadcast(this, null)
}
}
// 必须是静态
class MyBroadcastReceiver : BroadcastReceiver()
{
override fun onReceive(context: Context?, pIntent: Intent?)
{
Toast.makeText(context, "My Ordered Broadcast Receiver ", Toast.LENGTH_SHORT).show()
// 截断
abortBroadcast()
}
}
}
强制下线功能简述
- 在onResume()和onPasue()注册、取消,保证广播始终在顶层Activity
- 让所有Activity继承BaseActivity,在Broadcast中写onReceive()代码加入Dialog即可