You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Android中使用Kotlin实现每年固定日期推送用户通知的最优方案是什么

Android Kotlin实现年度指定日期发送通知的最优方案

核心选型说明

选择 AlarmManager 作为核心实现组件,WorkManager 仅适用于非时间敏感的后台任务,系统会对其做批量调度优化,无法保证每年固定日期准点触发,因此AlarmManager + 广播接收器是该需求的最优实现。

前置权限配置

需要提前申请的权限如下:

  • Android 13(API 33)及以上:POST_NOTIFICATIONS 运行时权限,是发送通知的前提
  • Android 12(API 31)及以上:SCHEDULE_EXACT_ALARM 权限,用于设置精确时间的闹钟
  • 系统重启监听权限:RECEIVE_BOOT_COMPLETED,用于系统重启后恢复闹钟配置
  • 可选适配:国产ROM(小米、华为、vivo等)需要引导用户开启应用自启动权限、加入省电白名单,避免应用被后台查杀后无法收到闹钟广播

核心实现步骤

1. 定义闹钟触发广播接收器

用于接收闹钟触发事件,触发后发送通知,代码如下:

class AnnualNotificationReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent?) {
        val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        
        // Android 8.0及以上需先创建通知渠道
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                "annual_notify_channel",
                "年度定时提醒",
                NotificationManager.IMPORTANCE_DEFAULT
            ).apply { description = "每年指定日期触发的通知提醒" }
            notificationManager.createNotificationChannel(channel)
        }

        // 构建通知,可根据需求自定义内容
        val notification = NotificationCompat.Builder(context, "annual_notify_channel")
            .setSmallIcon(R.drawable.ic_notification) // 替换为应用自身的通知图标
            .setContentTitle("年度提醒")
            .setContentText("你预设的年度提醒时间已到")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setAutoCancel(true)
            .build()

        notificationManager.notify((System.currentTimeMillis() % 10000).toInt(), notification)

        // 触发后自动设置下一年的闹钟
        val savedDate = getSavedTargetDate(context) // 从本地存储读取用户设置的月、日、时间
        setAnnualAlarm(context, savedDate.month, savedDate.day, savedDate.hour, savedDate.minute)
    }
}

在AndroidManifest.xml中注册该接收器:

<receiver
    android:name=".AnnualNotificationReceiver"
    android:exported="false" />

2. 实现年度闹钟设置方法

将用户设置的目标日期持久化存储到本地(如SharedPreferences),调用如下方法设置闹钟:

fun setAnnualAlarm(context: Context, targetMonth: Int, targetDay: Int, hour: Int, minute: Int) {
    val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
    val intent = Intent(context, AnnualNotificationReceiver::class.java)
    val pendingIntent = PendingIntent.getBroadcast(
        context,
        10001, // 固定唯一请求码,用于区分不同闹钟
        intent,
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )

    // 计算下次触发的时间戳
    val triggerTime = Calendar.getInstance().apply {
        set(Calendar.MONTH, targetMonth - 1) // Calendar月份从0开始计数
        set(Calendar.DAY_OF_MONTH, targetDay)
        set(Calendar.HOUR_OF_DAY, hour)
        set(Calendar.MINUTE, minute)
        set(Calendar.SECOND, 0)
        // 若今年的目标时间已过,自动顺延到下一年
        if (timeInMillis < System.currentTimeMillis()) {
            add(Calendar.YEAR, 1)
        }
    }.timeInMillis

    // 设置精确闹钟,低电模式下也可触发
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        alarmManager.setExactAndAllowWhileIdle(
            AlarmManager.RTC_WAKEUP,
            triggerTime,
            pendingIntent
        )
    } else {
        alarmManager.setExact(
            AlarmManager.RTC_WAKEUP,
            triggerTime,
            pendingIntent
        )
    }
}

注意:AlarmManager没有原生支持年度重复的触发配置,每次触发后必须手动重新设置下一年的闹钟

3. 处理系统重启后闹钟丢失问题

系统重启后所有AlarmManager设置的闹钟会被清空,需要监听开机广播重新设置:
首先在AndroidManifest.xml中添加权限和广播注册:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<receiver
    android:name=".BootCompleteReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

实现开机广播接收器:

class BootCompleteReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent?) {
        if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
            val savedDate = getSavedTargetDate(context)
            setAnnualAlarm(context, savedDate.month, savedDate.day, savedDate.hour, savedDate.minute)
        }
    }
}

适配注意事项

  • 每次设置闹钟前需要检查是否已获取SCHEDULE_EXACT_ALARM权限,Android 14及以上该权限需要用户主动授权,未授权时只能设置非精确闹钟,误差可达数小时
  • 若允许用户设置多个不同日期的年度提醒,需要为每个提醒分配不同的PendingIntent请求码,避免覆盖
  • 不要使用setRepeating方法设置年度重复,该方法设置的是不精确闹钟,无法保证触发时间准确性

内容的提问来源于stack exchange,提问作者Paweł Mańczak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 12:09:04