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

Android Studio应用定时通知无法正常触发问题求助

Android定时通知触发异常求助

开发Android应用时遇到定时通知触发异常:要么设置后立即触发,要么完全不发送通知。目前已成功创建通知渠道,但通知始终无法按时触发。

逻辑流程:启动Service从JSON读取数据(此环节正常),校验处理后调用setScheduleForINI(separateTime(iniTime), remTime)方法,其中iniTime为通知触发时间(HH:MM格式),remTime为通知间隔(分钟格式)。

定时任务设置逻辑

import android.app.AlarmManager
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale

@Suppress("PrivatePropertyName")
class AlarmService : Service() {
    private val logShow = LogShow()
    private val jsonManage = JsonManage()

    companion object {
        private const val CHANNEL_ID = "SonogiaAlarmChannel"
        private const val CHANNEL_NAME = "Sonogia"
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return START_STICKY
    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onCreate() {
        super.onCreate()
        createNotificationChannel()
        checkJsonGlobalSettings()
    }

    private fun createNotificationChannel() {
        val iniChannel = NotificationChannel(
            CHANNEL_ID,
            CHANNEL_NAME,
            NotificationManager.IMPORTANCE_HIGH
        ).apply {
            description = "Notificaciones de Sonogia"
            enableLights(true)
            enableVibration(true)
            setSound(null, null)
            lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
            setShowBadge(false)
        }
        val notificationManager: NotificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(iniChannel)
        logShow.logShowMsg("AlarmBGService", "Canal de notificaciones creado")
    }

    private fun checkJsonGlobalSettings() {
        logShow.logShowMsg("AlarmBGService", "Revisando configuracion")
        if (!jsonManage.globalCheck(this)) {
            logShow.logShowMsg("AlarmBGService", "Formato diario resibido")
            val date = Date()
            val dayOfWeek = SimpleDateFormat("EEEE", Locale.getDefault()).format(date)
            val alarmTimes = jsonManage.checkJsonAlarms(this, dayOfWeek)
            if (alarmTimes != null) {
                setNotification(alarmTimes[0], alarmTimes[1], alarmTimes[2])
            } else {
                Toast.makeText(this, "No hay alarmas configuradas", Toast.LENGTH_SHORT).show()
            }
        } else {
            logShow.logShowMsg("AlarmBGService", "Formato Global resibido")
            val alarmTimes = jsonManage.checkJsonAlarms(this, "Global")
            if (alarmTimes != null) {
                setNotification(alarmTimes[0], alarmTimes[1], alarmTimes[2])
            } else {
                Toast.makeText(this, "No hay alarmas configuradas", Toast.LENGTH_SHORT).show()
            }
        }
    }

    private fun setNotification(iniTime: String, remTime: String, wakeTime: String) {
        logShow.logShowMsg("AlarmBGService", "Configuracion leida: iniTime: $iniTime, remTime: $remTime, wakeTime: $wakeTime")
        logShow.logShowMsg("AlarmBGService", "Configurando alarmas: INI")
        setScheduleForINI(separateTime(iniTime), remTime)
        logShow.logShowMsg("AlarmBGService", "Configurando alarmas: WAKE")
        // AlarmReceiver.wakeNotification(wakeTime,this)
    }

    private fun separateTime(time: String): Array<String> {
        val parts = time.split(":")
        logShow.logShowMsg("AlarmBGService", "Hora: ${parts[0]}, Minuto: ${parts[1]}")
        return parts.toTypedArray()
    }

    private fun setScheduleForINI(iniTime: Array<String>, remTime: String) {
        logShow.logShowMsg("AlarmBGService", "IniHour: ${iniTime[0]}, IniMinute: ${iniTime[1]}")
        cancelAlarm() // Cancel existing alarm
        val intent = Intent(applicationContext, NotificationReceiver::class.java)
        val pendingIntent = PendingIntent.getBroadcast(
            applicationContext, 1, intent,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )
        val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
        val calendar = Calendar.getInstance().apply {
            timeInMillis = System.currentTimeMillis()
            set(Calendar.HOUR_OF_DAY, iniTime[0].toInt())
            set(Calendar.MINUTE, iniTime[1].toInt())
            set(Calendar.SECOND, 0)
        }
        logShow.logShowMsg("AlarmBGService", "Agendando a las: ${calendar.timeInMillis}")
        try {
            if (remTime.isNotEmpty()) {
                if (remTime.toInt() != 0) {
                    alarmManager.setInexactRepeating(
                        AlarmManager.RTC_WAKEUP,
                        calendar.timeInMillis,
                        remTime.toLong() * 1000 * 60,
                        pendingIntent
                    )
                    logShow.logShowMsg("AlarmBGService", "Agendado con intervalo remTime: $remTime")
                } else {
                    alarmManager.set(
                        AlarmManager.RTC_WAKEUP,
                        calendar.timeInMillis,
                        pendingIntent
                    )
                    logShow.logShowMsg("AlarmBGService", "Agendado sin intervalo remTime: $remTime")
                }
            }
        } catch (e: SecurityException) {
            logShow.logShowMsg("AlarmBGService", "Error al programar la alarma: ${e.message}")
        }
        logShow.logShowMsg("AlarmBGService", "Agendado")
    }

    private fun cancelAlarm() {
        val intent = Intent(applicationContext, NotificationReceiver::class.java)
        val pendingIntent = PendingIntent.getBroadcast(
            applicationContext, 1, intent,
            PendingIntent.FLAG_NO_CREATE // Cancel alarm if it exists
        )
        pendingIntent?.let {
            val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
            alarmManager.cancel(it)
            it.cancel()
            logShow.logShowMsg("AlarmBGService", "Alarm canceled")
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        cancelAlarm()
    }
}

通知创建逻辑

class NotificationReceiver : BroadcastReceiver() {
    private val logShow = LogShow()

    companion object{
        private const val NOTIFICATION_ID = 1
        private const val CHANNEL_ID = "SonogiaAlarmChannel"
    }

    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    override fun onReceive(context: Context, intent: Intent) {
        iniNotification(context)
        val stop = intent?.getStringExtra("A dormir")
        if (stop == "A dormir"){
            logShow.logShowMsg("NotificationReceiver", "Repeticion detenida")
            Toast.makeText(context, "Buenas noches", Toast.LENGTH_SHORT).show()
        }
    }

    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    private fun iniNotification(context: Context) {
        val iniRemoteViews = RemoteViews(context.packageName, R.layout.notification_layout)
        iniRemoteViews.setOnClickPendingIntent(
            R.id.cancel_button,
            PendingIntent.getBroadcast(
                context, 0,
                Intent(context, NotificationReceiver::class.java).putExtra("action", "cancel_rem"),
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )
        )
        val pendingIntent = PendingIntent.getBroadcast(
            context, 0,
            Intent(context, NotificationReceiver::class.java).putExtra("A dormir", "A dormir"),
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
        )
        val iniNotification = NotificationCompat.Builder(context, CHANNEL_ID)
            .setContentTitle("Buenas noches")
            .setContentText("Ha llegado la hora de dormir, te deseamos dulces sueños. Att: Sonogia")
            .setSmallIcon(R.mipmap.ic_launcher_round)
            .setCustomContentView(iniRemoteViews)
            .addAction(0, "A dormir", pendingIntent)
        val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        manager.notify(NOTIFICATION_ID, iniNotification)
        logShow.logShowMsg("NotificationReceiver", "IniNotification enviada")
    }
}

已尝试使用setExact等多种AlarmManager方法,调整执行逻辑,前置的JSON读取、参数解析流程均正常,但通知仍无法按时触发,请求协助排查问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 20:35:05