broadcast intent
概述
Intent可以使用sendBroadcast(), 在应用组件之间广播事件;
使用BroadReceiver类监听和响应Broadcast Intent, 需要注册(register)和过滤器(intent-filter);
接受系统broadcast: 重启后唤醒
无论何时,只要打开设备,系统就会会发送带有BOOT_COMPLETED操作的broadcast intent
一. 创建并登记standalone receiver
- StartupReceiver.xml
class StartupReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Log.i(TAG,"Recevived broadcast intent: " + intent?.action)
}
companion object{
val TAG = "StartupReceiver"
}
}
- 在 manifes文件中添加reveiver
AndroidManifest.xml
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
...
<application
<receiver android:name=".StartupReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
- 然后系统重启后,broadcast reveiver就会醒来接受。
二. recevier
recevier生命周期非常短暂,可以用来启动activity和service
1.添加定时器
QueryPreferences.kt
val PREF_IS_ALARM_ON = "isAlarmOn"
fun isAlarmOn(context: Context): Boolean {
return PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(PREF_IS_ALARM_ON, false)
}
fun setAlarmOn(context: Context, isOn: Boolean) {
PreferenceManager.getDefaultSharedPreferences(context)
.edit()
.putBoolean(PREF_IS_ALARM_ON, isOn)
.apply()
}
- 存储定时器状态
val TAG = "PollService"
val POLL_INTERVAL_MS = TimeUnit.SECONDS.toSeconds(10)//间隔1分钟
/**
* 添加定时器方法
*/
fun setServiceAlarm(context: Context, isOn: Boolean) {
var i = PollService.newIntent(context)
/**
* 创建一个用来启动PollService的PendingIntent, PendingIntent.getService(...)方法打包了一个ContextStartService(intent)方法的调用
*
*/
var pi = PendingIntent.getService(context, 0, i, 0)
var alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
if (isOn) {
// 设置定时器,第一个参数描述定时器基准常量,第二个参数第十七启动时间,第三个参数定时器循环间隔,第四个参数要发送到的PendingIntent
alarmManager.setRepeating(
AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime(),
POLL_INTERVAL_MS, pi
)
} else {
alarmManager.cancel(pi)//取消定时器
pi.cancel()//取消PendingIntent
}
QueryPreferences.setAlarmOn(context, isOn)
}
5.设备重启后启动定时器
class StartupReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Log.i(TAG, "Recevived broadcast intent: " + intent?.action)
context?.let {
var isOn = QueryPreferences.isAlarmOn(it)
PollService.setServiceAlarm(it, isOn)
}
}
companion object {
val TAG = "StartupReceiver"
}
}
过滤前台消息通知消息
一. 发送broadcast intent
val ACTION_SHOW_NOTIFICATION = "com.bignnerdranch.android.photogallery.SHOW_NOTIFICATION"
sendBroadcast(Intent(ACTION_SHOW_NOTIFICATION))
二. 创建并登记receiver接受broadcast intent
VisibleFragment.kt
abstract class VisibleFragment : Fragment() {
//开启recevier
override fun onStart() {
super.onStart()
var filter = IntentFilter(PollService.ACTION_SHOW_NOTIFICATION)
activity?.registerReceiver(mOnShowNotification, filter)
}
// 注销receiver
override fun onStop() {
super.onStop()
activity?.unregisterReceiver(mOnShowNotification)
}
// 定义一个内部receiver
var mOnShowNotification = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
Toast.makeText(activity, "Got a broadcast:" + intent?.action, Toast.LENGTH_LONG).show()
}
}
companion object {
val TAG = "VisibleFragment"
}
}
以上代码和创建的IntentFilter和下面的效果一样的
<intent-filter>
<action android:name="com.example.apps.photogallery.ACTION_SHOW_NOTIFICATION "/>
</intent-filter>
- 现在任何继承VisibleFragment.kt的fragment都可以接收到Broadcast intent信息
使用私有权限限制broadcast
使用动态broadcast receiver存在一个问题,即系统中的任何应用均可监听并触发你的receiver
有多种办法阻止
- 给receiver标签加一个android:exported="false"声明仅限应用内部使用
- 另外也可以创建自己的使用权限
- AndroidManifest.xml
<permission android:name="com.example.apps.photogallery.PRIVATE"
android:protectionLevel="signature"/> 声明权限
<uses-permission android:name="com.example.apps.photogallery.PRIVATE"/>获取权限
- 使用权限
val ACTION_SHOW_NOTIFICATION = "com.bignnerdranch.android.photogallery.SHOW_NOTIFICATION"
val PERM_PRIVATE = "com.example.apps.photogallery.PRIVATE"
sendBroadcast(Intent(ACTION_SHOW_NOTIFICATION), PERM_PRIVATE)
- 动态注册权限
VisibleFragment.kt
//开启recevier
override fun onStart() {
super.onStart()
var filter = IntentFilter(PollService.ACTION_SHOW_NOTIFICATION)
activity?.registerReceiver(mOnShowNotification, filter, PollService.PERM_PRIVATE, null)
}