Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.ccextractor.ultimate_alarm_clock

import android.app.PendingIntent
import android.content.Context
import android.content.Intent

internal enum class AlarmPendingIntentKind(
val requestCode: Int,
val isBroadcast: Boolean,
) {
MAIN_ALARM(0, true),
LEGACY_BOOT_ALARM(1, true),
ACTIVITY_CHECK(4, false),
LOCATION_CHECK(5, false),
WEATHER_CHECK(6, false),
}

internal object AlarmPendingIntents {
private const val FLAGS = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE

fun broadcast(
context: Context,
kind: AlarmPendingIntentKind,
intent: Intent,
): PendingIntent {
require(kind.isBroadcast) { "$kind must use a broadcast PendingIntent" }
return PendingIntent.getBroadcast(
context,
kind.requestCode,
intent,
FLAGS
)
}

fun service(
context: Context,
kind: AlarmPendingIntentKind,
intent: Intent,
): PendingIntent {
require(!kind.isBroadcast) { "$kind must use a service PendingIntent" }
return PendingIntent.getService(
context,
kind.requestCode,
intent,
FLAGS
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package com.ccextractor.ultimate_alarm_clock

import android.annotation.SuppressLint
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
Expand Down Expand Up @@ -68,18 +67,16 @@ class BootReceiver : BroadcastReceiver() {
fun scheduleAlarm(milliSeconds: Long, context: Context, activityMonitor: Any) {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(context, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
val pendingIntent = AlarmPendingIntents.broadcast(
context,
1,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
AlarmPendingIntentKind.LEGACY_BOOT_ALARM,
intent
)
val activityCheckIntent = Intent(context, ScreenMonitorService::class.java)
val pendingActivityCheckIntent = PendingIntent.getService(
val pendingActivityCheckIntent = AlarmPendingIntents.service(
context,
4,
activityCheckIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
AlarmPendingIntentKind.ACTIVITY_CHECK,
activityCheckIntent
)
// Schedule the alarm
val tenMinutesInMilliseconds = 600000L
Expand Down Expand Up @@ -156,4 +153,4 @@ class BootReceiver : BroadcastReceiver() {
String.format("%02d:%02d", minutes, seconds)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.app.ActivityManager
import android.app.AlarmManager
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
Expand Down Expand Up @@ -211,18 +210,16 @@ class MainActivity : FlutterActivity() {

val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(this, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
val pendingIntent = AlarmPendingIntents.broadcast(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
AlarmPendingIntentKind.MAIN_ALARM,
intent
)
val activityCheckIntent = Intent(this, ScreenMonitorService::class.java)
val pendingActivityCheckIntent = PendingIntent.getService(
val pendingActivityCheckIntent = AlarmPendingIntents.service(
this,
4,
activityCheckIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
AlarmPendingIntentKind.ACTIVITY_CHECK,
activityCheckIntent
)
// Schedule the alarm
val tenMinutesInMilliseconds = 600000L
Expand Down Expand Up @@ -254,11 +251,10 @@ class MainActivity : FlutterActivity() {
editor.putInt("flutter.is_location_on", 1)
editor.apply()
val locationAlarmIntent = Intent(this, LocationFetcherService::class.java)
val pendingLocationAlarmIntent = PendingIntent.getService(
val pendingLocationAlarmIntent = AlarmPendingIntents.service(
this,
5,
locationAlarmIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
AlarmPendingIntentKind.LOCATION_CHECK,
locationAlarmIntent
)
val alarmClockInfo = AlarmManager.AlarmClockInfo(triggerTime - 10000, pendingIntent)
alarmManager.setAlarmClock(
Expand All @@ -273,11 +269,10 @@ class MainActivity : FlutterActivity() {
Log.d("we", getWeatherConditions(weatherTypes))
editor.apply()
val weatherAlarmIntent = Intent(this, WeatherFetcherService::class.java)
val pendingWeatherAlarmIntent = PendingIntent.getService(
val pendingWeatherAlarmIntent = AlarmPendingIntents.service(
this,
6,
weatherAlarmIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
AlarmPendingIntentKind.WEATHER_CHECK,
weatherAlarmIntent
)
val alarmClockInfo = AlarmManager.AlarmClockInfo(triggerTime - 10000, pendingIntent)
alarmManager.setAlarmClock(
Expand All @@ -295,26 +290,47 @@ class MainActivity : FlutterActivity() {
private fun cancelAllScheduledAlarms() {
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(this, AlarmReceiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(
val pendingIntent = AlarmPendingIntents.broadcast(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
AlarmPendingIntentKind.MAIN_ALARM,
intent
)
val legacyBootPendingIntent = AlarmPendingIntents.broadcast(
this,
AlarmPendingIntentKind.LEGACY_BOOT_ALARM,
intent
)

val activityCheckIntent = Intent(this, ScreenMonitorService::class.java)
val pendingActivityCheckIntent = PendingIntent.getService(
val pendingActivityCheckIntent = AlarmPendingIntents.service(
this,
AlarmPendingIntentKind.ACTIVITY_CHECK,
activityCheckIntent
)
val locationIntent = Intent(this, LocationFetcherService::class.java)
val pendingLocationIntent = AlarmPendingIntents.service(
this,
AlarmPendingIntentKind.LOCATION_CHECK,
locationIntent
)
val weatherIntent = Intent(this, WeatherFetcherService::class.java)
val pendingWeatherIntent = AlarmPendingIntents.service(
this,
4,
activityCheckIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
AlarmPendingIntentKind.WEATHER_CHECK,
weatherIntent
)

// Cancel any existing alarms by providing the same pending intent
alarmManager.cancel(pendingIntent)
pendingIntent.cancel()
alarmManager.cancel(legacyBootPendingIntent)
legacyBootPendingIntent.cancel()
alarmManager.cancel(pendingActivityCheckIntent)
pendingActivityCheckIntent.cancel()
alarmManager.cancel(pendingLocationIntent)
pendingLocationIntent.cancel()
alarmManager.cancel(pendingWeatherIntent)
pendingWeatherIntent.cancel()

}

Expand Down Expand Up @@ -556,4 +572,4 @@ class MainActivity : FlutterActivity() {
Log.i("SystemRingtone", "=== END DIAGNOSTICS ===")
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.ccextractor.ultimate_alarm_clock

import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertTrue
import org.junit.Test

class AlarmPendingIntentContractTest {
@Test
fun `main and legacy boot alarms keep different request codes`() {
assertNotEquals(
AlarmPendingIntentKind.MAIN_ALARM.requestCode,
AlarmPendingIntentKind.LEGACY_BOOT_ALARM.requestCode
)
assertTrue(AlarmPendingIntentKind.MAIN_ALARM.isBroadcast)
assertTrue(AlarmPendingIntentKind.LEGACY_BOOT_ALARM.isBroadcast)
}

@Test
fun `service request codes stay stable`() {
assertEquals(4, AlarmPendingIntentKind.ACTIVITY_CHECK.requestCode)
assertEquals(5, AlarmPendingIntentKind.LOCATION_CHECK.requestCode)
assertEquals(6, AlarmPendingIntentKind.WEATHER_CHECK.requestCode)
}
}