[Android]使用AlarmManager设置周期性任务
设置周期性任务每隔一小时执行一次任务
闹钟
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.SystemClock
/// 4.设置闹钟
/// 1小时
fun setupAlarmAction(context: Context) {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, MyAlarmReceiver::class.java)
// 设置 PendingIntent 时使用了 PendingIntent.FLAG_UPDATE_CURRENT 标志,这意味着如果相同的 PendingIntent 已经存在,它将被更新,而不是创建新的 PendingIntent。
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
// 设置每小时触发一次的闹钟
val interval = AlarmManager.INTERVAL_HOUR
val triggerAtMillis = SystemClock.elapsedRealtime() + interval
alarmManager.setInexactRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
triggerAtMillis,
interval,
pendingIntent
)
}
/// 30秒
fun setupAlarmAction1(context: Context) {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, MyAlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
// 设置每30秒触发一次的闹钟
val interval: Long = 20000L // 30秒 = 30,000毫秒
val triggerAtMillis = SystemClock.elapsedRealtime() + interval
alarmManager.setRepeating(
AlarmManager.ELAPSED_REALTIME_WAKEUP,
triggerAtMillis,
interval,
pendingIntent
)
}
MyAlarmReceiver
import android.app.ActivityManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.PowerManager
import com.mofang.call.callphone.utils.NSLog
/// 每小时打开屏幕一次,避免设备强制睡眠
class MyAlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
NSLog("MyAlarmReceiver onReceive")
// 重启应用
restartApp(context)
}
/**
* 检查应用是否正在运行:通过 ActivityManager 检查应用是否正在运行。
* 根据应用状态决定是否重启:如果应用正在运行,则只打开应用;如果应用被杀掉,则重启应用。
* */
private fun restartApp(context: Context) {
val packageManager = context.packageManager
val packageName = context.packageName
val intent = packageManager.getLaunchIntentForPackage(packageName)
if (intent != null) {
NSLog("MyAlarmReceiver 重启APP")
/// 2
if (isAppInForeground(context, packageName)) {
// 如果应用正在前台运行,忽略启动操作
NSLog("应用正在前台运行,忽略启动操作")
return
} else {
// 打开屏幕
NSLog("打开屏幕")
// 获取电源管理器
val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
// 获取 PowerManager 实例,用于控制设备电源状态
val wakeLock = powerManager.newWakeLock(
PowerManager.FULL_WAKE_LOCK or
PowerManager.ACQUIRE_CAUSES_WAKEUP or
PowerManager.ON_AFTER_RELEASE, "MyApp::MyWakeLockTag"
)
// 创建一个 WakeLock,确保设备在启动应用时保持唤醒状态。获取 WakeLock 并保持 10 分钟(防止设备在这段时间内进入休眠)
wakeLock.acquire(10*60*1000L /*10 minutes*/)
// 释放 WakeLock,允许设备在适当时机进入休眠
wakeLock.release()
}
}
}
/// 判断APP是否在前台运行
private fun isAppInForeground(context: Context, packageName: String): Boolean {
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val runningAppProcesses = activityManager.runningAppProcesses
for (processInfo in runningAppProcesses) {
if (processInfo.processName == packageName) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
return true
}
}
}
return false
}
}
AndroidManifest.xml
<!-- AlarmManager闹钟管理权限 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application>
<!-- 闹钟管理 -->
<receiver android:name=".MyAlarmReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
首页
当你从登录页进入首页时设置了一次 AlarmManager 闹钟,然后退出登录再次进入首页并重新设置一次 AlarmManager 闹钟,此时你实际上只有一个闹钟。原因是你在设置 PendingIntent 时使用了 PendingIntent.FLAG_UPDATE_CURRENT 标志,这意味着如果相同的 PendingIntent 已经存在,它将被更新,而不是创建新的 PendingIntent。
/**
* 首页
* */
class StartPageActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 设置 AlarmManager
setupAlarmAction(this)
}
}