Pith - wedge_android
wedge_android/app/src/main/java/com/vgmlr/wedge/WedgeAlarmReceiver.kt [4.5 kb]
Modified: 06:16:53 91 026 (18 Jun 026)
6 Days Ago
package com.vgmlr.wedge

import android.app.AlarmManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Locale

class WedgeAlarmReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val action = intent.action
        if (action == "com.vgmlr.wedge.ACTION_CHECK_ALARM" || action == Intent.ACTION_BOOT_COMPLETED) {

            val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
            val nextIntent = Intent(context, WedgeAlarmReceiver::class.java).apply {
                this.action = "com.vgmlr.wedge.ACTION_CHECK_ALARM"
            }
            val pendingIntent = PendingIntent.getBroadcast(
                context, 2026, nextIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )
            val triggerAt = System.currentTimeMillis() + 60000L
            try {
                if (android.os.Build.VERSION.SDK_INT < 31 || alarmManager.canScheduleExactAlarms()) {
                    alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt, pendingIntent)
                } else {
                    alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt, pendingIntent)
                }
            } catch (_: SecurityException) {
                alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAt, pendingIntent)
            }

            val database = AppDatabase.getInstance(context)
            val preferenceManager = PreferenceManager(context)

            CoroutineScope(Dispatchers.IO).launch {

                NoteWidgetProvider.triggerUpdate(context)
                val note = database.noteDao().getNoteSync() ?: return@launch
                val currentText = note.content

                val now = Calendar.getInstance()
                val hour = String.format(Locale.US, "%02d", now.get(Calendar.HOUR_OF_DAY))
                val minute = String.format(Locale.US, "%02d", now.get(Calendar.MINUTE))
                val targetHHMM = "$hour:$minute"

                val otcDay = WedgeDate.getOtcParts(now.timeInMillis).first
                val dayOfWeek = SimpleDateFormat("EEE", Locale.US).format(now.time)
                val dayOfMonth = now.get(Calendar.DAY_OF_MONTH)
                val month = SimpleDateFormat("MMM", Locale.US).format(now.time)

                val targetHeaderPattern = """(?i)$otcDay\s+$dayOfWeek\s+0?$dayOfMonth\s+$month"""

                val triggeredLine = getTriggeredAlarmLine(currentText, targetHeaderPattern, targetHHMM)
                if (triggeredLine != null) {
                    val soundUri = preferenceManager.alarmSoundUri.firstOrNull() ?: ""
                    val durationMinutes = preferenceManager.alarmDurationMinutes.firstOrNull() ?: 5
                    val vibrationEnabled = preferenceManager.vibrationEnabled.firstOrNull() ?: false

                    val serviceIntent = Intent(context, WedgeAlarmPlayback::class.java).apply {
                        putExtra("ALARM_SOUND_URI", soundUri)
                        putExtra("ALARM_DURATION_MINUTES", durationMinutes)
                        putExtra("ALARM_EVENT_TEXT", triggeredLine)
                        putExtra("ALARM_VIBRATION_ENABLED", vibrationEnabled)
                    }
                    context.startForegroundService(serviceIntent)
                }
            }
        }
    }

    private fun getTriggeredAlarmLine(text: String, headerPattern: String, currentHHMM: String): String? {
        val headerRegex = Regex(headerPattern)
        val match = headerRegex.find(text) ?: return null

        val sub = text.substring(match.range.first)
        val lines = sub.split("\n")

        for (i in 1 until lines.size) {
            val line = lines[i]
            if (line.trim().isEmpty()) continue

            if (Regex("""^\d{1,3}\s+[a-zA-Z]{3}""").containsMatchIn(line)) break

            val alarmMatch = WedgeRegex.ALARM_TIME.find(line.trim())
            if (alarmMatch != null) {
                val extractedTime = "${alarmMatch.groupValues[1]}:${alarmMatch.groupValues[2]}"
                if (extractedTime == currentHHMM) {
                    return line.trim()
                }
            }
        }
        return null
    }
}
Updates
OTC Applet - Linux 93.026.1
Wedge - Linux 90.026.1
Wedge - Android 90.026.1
Shim - Android 86.026.1
Kerf - Android 86.026.4
Dev
TVShow (227) 'CSA'
TVShow (228) 'APT'
TVProgram (83) 'BXT'
Miter Update(s)
Peen (Messaging)

Menu
Calendar
Project Tin (024/029)
Miter
RSS Feed
User Avatar
@vgmlr
=SUM(parts)