[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)
    }

}