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

Kotlin安卓应用定时通知仅上午触发,下午PM时段不生效如何解决?

问题根因

你的代码核心问题是缺失12小时制到24小时制的转换逻辑:

  • 界面展示用的是12小时制(带PM后缀),比如晚上8点你存入SharedPreferences的asarTimeHour值是8,但你赋值用的Calendar.HOUR_OF_DAY是24小时制字段,值8对应上午8点,自然只会在上午触发。
  • 两个潜在问题:如果设置时间早于当前系统时间,取到的是当天过去的时间,会导致定时直接触发或者延后到第二天;Android 12及以上版本PendingIntent必须加FLAG_IMMUTABLE或FLAG_MUTABLE标识,否则定时会失效甚至崩溃。

修复方案

1. 新增上午/下午状态存储

用户选择时间时,除了存小时、分钟,额外存一个布尔字段isAsarTimePm,PM时段存true,AM时段存false,其余4个定时任务同理添加对应标识字段。

2. 小时制转换+时间有效性判断

给Calendar赋值时把12小时制转为24小时制,同时判断时间是否已过,已过则自动延后到第二天。

3. 兼容高版本安卓的PendingIntent规则

适配Android 12+的PendingIntent标识要求,同时将精度低的setInexactRepeating替换为准点生效的setExactAndAllowWhileIdle,更适合礼拜通知这类对时间精度要求高的场景。

修复后代码

定时触发逻辑代码

asrSwitch.setOnCheckedChangeListener { buttonView, isChecked ->
    if (isChecked){
        editor.putBoolean("asarTimesSwitch",true)
        editor.putBoolean("asarTXT", true)
        editor.apply()
        asrSwitch.isChecked = true
        val asarTime = getSharedPreferences("saveSettingData", Context.MODE_PRIVATE)

        calender = Calendar.getInstance()
        // 取出存储的12小时制时间和时段标识
        val saveHour = asarTime.getInt("asarTimeHour", 0)
        val isPm = asarTime.getBoolean("isAsarTimePm", false)
        val saveMinute = asarTime.getInt("asarTimeMinutes",0)
        // 转换为24小时制,处理12点的特殊边界
        val hour24 = if (isPm) {
            if (saveHour == 12) 12 else saveHour + 12
        } else {
            if (saveHour == 12) 0 else saveHour
        }
        calender[Calendar.HOUR_OF_DAY] = hour24
        calender[Calendar.MINUTE] = saveMinute
        calender[Calendar.SECOND] = 0
        calender[Calendar.MILLISECOND] = 0
        
        // 时间已过则自动延后到第二天
        if (calender.timeInMillis < System.currentTimeMillis()) {
            calender.add(Calendar.DAY_OF_MONTH, 1)
        }

        // 界面保持12小时制展示
        asrTxt.text = "$saveHour:$saveMinute ${if (isPm) "PM" else "AM"}"

        alarmAsr()

    }else{
        editor.putBoolean("asarTimesSwitch",false)
        editor.putBoolean("asarTXT", false)
        editor.apply()
        asrSwitch.isChecked = false
        asrTxt.text = " "
    }
}

定时任务代码

fun alarmAsr(){
    alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager
    val i = Intent(this, asarBroadcastReceiver::class.java)
    // 兼容Android 12+的PendingIntent标识要求
    val flag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    } else {
        PendingIntent.FLAG_UPDATE_CURRENT
    }
    pendingIntent = PendingIntent.getBroadcast(this, 4, i, flag)

    // 准点触发,支持低电模式生效
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        alarmManager.setExactAndAllowWhileIdle(
            AlarmManager.RTC_WAKEUP,
            calender.timeInMillis,
            pendingIntent
        )
    } else {
        alarmManager.setExact(
            AlarmManager.RTC_WAKEUP,
            calender.timeInMillis,
            pendingIntent
        )
    }
}

如果需要每天重复触发,只需在对应广播接收器的onReceive方法里,触发通知后重新调用一次定时设置方法,即可注册第二天的准点通知。

内容的提问来源于stack exchange,提问作者Abood

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 20:57:02