I've been working on this project for a few days, and either it sends a notification at the moment I schedule it or never. As it stands right now, it creates the channel and the notification, but it never gets sent.
The logic goes this way: First, I start a Service(), which gets data from a JSON (this works perfectly). After some checks and processing, it passes through this process: setScheduleForINI(separateTime(iniTime), remTime) iniTime is the time when the notification should pop up; it's in the format HH:MM. remTime is the interval between notifications; it's in the format MM.
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()
}
}
this is where all takes place
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")
}
}
and this is where i create the notificication i need to send
i've tryed with diferents methods for seending the notification, with setExact, the place of execution and and other logics, and everything before this works correctly