diff --git a/.gitignore b/.gitignore index 6d40eb7df..c74c59b1c 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,5 @@ app/.cifuzz-corpus/ gradle/gradle-daemon-jvm.properties # Kotlin -.kotlin \ No newline at end of file +.kotlin +/caveman.json diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ad700a8ef..216f1d67c 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -22,8 +22,8 @@ android { minSdk = 28 multiDexEnabled = true targetSdk = 36 - versionCode = 167 - versionName = "1.22.12" + versionCode = 168 + versionName = "1.22.13" base.archivesName = "MedTimer" // Use this deprecated setting because Android Lint will not pick up androidResources.localeFilters correctly @Suppress("DEPRECATION") diff --git a/app/src/full/java/com/futsch1/medtimer/location/GeofenceBroadcastReceiver.kt b/app/src/full/java/com/futsch1/medtimer/location/GeofenceBroadcastReceiver.kt index 19a227af9..d368c6eda 100644 --- a/app/src/full/java/com/futsch1/medtimer/location/GeofenceBroadcastReceiver.kt +++ b/app/src/full/java/com/futsch1/medtimer/location/GeofenceBroadcastReceiver.kt @@ -5,10 +5,13 @@ import android.content.Context import android.content.Intent import android.util.Log import com.futsch1.medtimer.LogTags +import com.futsch1.medtimer.di.ApplicationScope import com.futsch1.medtimer.reminders.LocationSnoozeProcessor import com.google.android.gms.location.Geofence import com.google.android.gms.location.GeofencingEvent import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import javax.inject.Inject @AndroidEntryPoint @@ -17,6 +20,10 @@ class GeofenceBroadcastReceiver : BroadcastReceiver() { @Inject lateinit var locationSnoozeProcessor: LocationSnoozeProcessor + @Inject + @ApplicationScope + lateinit var applicationScope: CoroutineScope + override fun onReceive(context: Context, intent: Intent) { val event = GeofencingEvent.fromIntent(intent) ?: return handleGeofencingEvent(event) @@ -28,7 +35,9 @@ class GeofenceBroadcastReceiver : BroadcastReceiver() { return } if (event.geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || event.geofenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL) { - locationSnoozeProcessor.processLocationSnooze() + applicationScope.launch { + locationSnoozeProcessor.processLocationSnooze() + } } } } diff --git a/app/src/main/java/com/futsch1/medtimer/alarm/ReminderAlarmActivity.kt b/app/src/main/java/com/futsch1/medtimer/alarm/ReminderAlarmActivity.kt index 70df2f942..3f1329282 100644 --- a/app/src/main/java/com/futsch1/medtimer/alarm/ReminderAlarmActivity.kt +++ b/app/src/main/java/com/futsch1/medtimer/alarm/ReminderAlarmActivity.kt @@ -96,14 +96,23 @@ class ReminderAlarmActivity : AppCompatActivity() { } else { this@ReminderAlarmActivity } - mediaPlayer = - MediaPlayer.create( - audioContext, - preferencesDataSource.preferences.value.alarmRingtone ?: Settings.System.DEFAULT_ALARM_ALERT_URI, - null, - AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM).build(), - 0 - ).apply { isLooping = true } + val tmpMediaPlayer = MediaPlayer.create( + audioContext, + preferencesDataSource.preferences.value.alarmRingtone ?: Settings.System.DEFAULT_ALARM_ALERT_URI, + null, + AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM).build(), + 0 + ) ?: MediaPlayer.create( + audioContext, + Settings.System.DEFAULT_ALARM_ALERT_URI, + null, + AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM).build(), + 0 + ) + if (tmpMediaPlayer != null) { + tmpMediaPlayer.isLooping = true + mediaPlayer = tmpMediaPlayer + } } private suspend fun startAlarm() { @@ -136,6 +145,7 @@ class ReminderAlarmActivity : AppCompatActivity() { private fun releaseMediaPlayer() { mediaPlayer?.release() + mediaPlayer = null Log.d("ReminderAlarm", "Released media player") } @@ -178,7 +188,7 @@ class ReminderAlarmActivity : AppCompatActivity() { reminderNotificationData: ReminderNotificationData ): Intent { val intent = Intent(context, ReminderAlarmActivity::class.java).apply { - setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP) + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP } reminderNotificationData.toIntent(intent) diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/AlarmProcessor.kt b/app/src/main/java/com/futsch1/medtimer/reminders/AlarmProcessor.kt index 43d286763..037d139db 100644 --- a/app/src/main/java/com/futsch1/medtimer/reminders/AlarmProcessor.kt +++ b/app/src/main/java/com/futsch1/medtimer/reminders/AlarmProcessor.kt @@ -24,7 +24,7 @@ class AlarmProcessor @Inject constructor( ) { private val exactReminders: Boolean = preferencesDataSource.preferences.value.exactReminders - fun setAlarmForReminderNotification(scheduledReminderNotificationData: ReminderNotificationData) { + suspend fun setAlarmForReminderNotification(scheduledReminderNotificationData: ReminderNotificationData, reminderNotificationProcessor: ReminderNotificationProcessor? = null) { val originalInstant = scheduledReminderNotificationData.remindInstant scheduledReminderNotificationData.remindInstant = adjustTimestamp(timeAccess, originalInstant) @@ -49,9 +49,13 @@ class AlarmProcessor @Inject constructor( scheduledReminderNotificationData ) ) - val reminderIntent = getReminderAction(context) - scheduledReminderNotificationData.toIntent(reminderIntent) - context.sendBroadcast(reminderIntent, RECEIVER_PERMISSION) + if (reminderNotificationProcessor == null) { + val reminderIntent = getReminderAction(context) + scheduledReminderNotificationData.toIntent(reminderIntent) + context.sendBroadcast(reminderIntent, RECEIVER_PERMISSION) + } else { + reminderNotificationProcessor.processReminders(scheduledReminderNotificationData) + } return } diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/LocationSnoozeProcessor.kt b/app/src/main/java/com/futsch1/medtimer/reminders/LocationSnoozeProcessor.kt index 41923f6b9..58e5dae7c 100644 --- a/app/src/main/java/com/futsch1/medtimer/reminders/LocationSnoozeProcessor.kt +++ b/app/src/main/java/com/futsch1/medtimer/reminders/LocationSnoozeProcessor.kt @@ -11,7 +11,7 @@ class LocationSnoozeProcessor @Inject constructor( private val persistentDataDataSource: PersistentDataDataSource, private val geofenceRegistrar: GeofenceRegistrar ) { - fun processLocationSnooze() { + suspend fun processLocationSnooze() { val pending = persistentDataDataSource.getPendingLocationSnoozes() Log.d(LogTags.REMINDER, "In home location, restoring ${pending.size} snoozed reminders") for (data in pending) { diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/NotificationProcessor.kt b/app/src/main/java/com/futsch1/medtimer/reminders/NotificationProcessor.kt index 45518e9e6..3a7862ea4 100644 --- a/app/src/main/java/com/futsch1/medtimer/reminders/NotificationProcessor.kt +++ b/app/src/main/java/com/futsch1/medtimer/reminders/NotificationProcessor.kt @@ -30,7 +30,6 @@ import javax.inject.Inject class NotificationProcessor @Inject constructor( private val alarmProcessor: AlarmProcessor, private val notifications: Notifications, - private val scheduleNextReminderNotificationProcessor: ScheduleNextReminderNotificationProcessor, private val stockHandlingProcessor: StockHandlingProcessor, private val repeatProcessor: RepeatProcessor, private val notificationManager: NotificationManager, @@ -56,8 +55,6 @@ class NotificationProcessor @Inject constructor( setReminderEventStatus(status, reminderEventsToUpdate) - // Reschedule since the trigger condition for a linked reminder might have changed - scheduleNextReminderNotificationProcessor.scheduleNextReminder() } fun cancelNotification(notificationId: Int) { diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/ReminderNotificationProcessor.kt b/app/src/main/java/com/futsch1/medtimer/reminders/ReminderNotificationProcessor.kt index 1431f5bfb..1f9617531 100644 --- a/app/src/main/java/com/futsch1/medtimer/reminders/ReminderNotificationProcessor.kt +++ b/app/src/main/java/com/futsch1/medtimer/reminders/ReminderNotificationProcessor.kt @@ -28,7 +28,6 @@ class ReminderNotificationProcessor @Inject constructor( val notifications: Notifications, val notificationProcessor: NotificationProcessor, val repeatProcessor: RepeatProcessor, - val scheduleNextReminderNotificationProcessor: ScheduleNextReminderNotificationProcessor, private val reminderNotificationFactory: ReminderNotificationFactory, private val reminderEventRepository: ReminderEventRepository, private val preferencesDataSource: PreferencesDataSource @@ -46,9 +45,6 @@ class ReminderNotificationProcessor @Inject constructor( notificationAction(nonTakenReminderNotification) } - val processedEvents = nonTakenReminderNotification.reminderNotificationParts.map { it.reminderEvent } - scheduleNextReminderNotificationProcessor.scheduleNextReminder(processedEvents) - return true } diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/ReminderProcessorBroadcastReceiver.kt b/app/src/main/java/com/futsch1/medtimer/reminders/ReminderProcessorBroadcastReceiver.kt index c8415e276..379df3c13 100644 --- a/app/src/main/java/com/futsch1/medtimer/reminders/ReminderProcessorBroadcastReceiver.kt +++ b/app/src/main/java/com/futsch1/medtimer/reminders/ReminderProcessorBroadcastReceiver.kt @@ -3,7 +3,10 @@ package com.futsch1.medtimer.reminders import android.content.BroadcastReceiver import android.content.Context import android.content.Intent +import android.os.Bundle +import android.util.Log import com.futsch1.medtimer.ActivityCodes +import com.futsch1.medtimer.LogTags import com.futsch1.medtimer.ProcessorCode import com.futsch1.medtimer.di.ApplicationScope import com.futsch1.medtimer.model.Reminder @@ -61,24 +64,39 @@ class ReminderProcessorBroadcastReceiver : BroadcastReceiver() { val pendingResult = goAsync() applicationScope.launch { try { + Log.d(LogTags.REMINDER, "Received intent $intentAction") when (intentAction) { - ProcessorCode.Dismissed -> notificationProcessor.processReminderEventsInNotification( - ProcessedNotificationData.fromBundle(intent.extras!!), - ReminderEvent.ReminderStatus.SKIPPED - ) - - ProcessorCode.Taken -> notificationProcessor.processReminderEventsInNotification( - ProcessedNotificationData.fromBundle(intent.extras!!), - ReminderEvent.ReminderStatus.TAKEN - ) - - ProcessorCode.Acknowledged -> notificationProcessor.processReminderEventsInNotification( - ProcessedNotificationData.fromBundle(intent.extras!!), - ReminderEvent.ReminderStatus.ACKNOWLEDGED - ) + ProcessorCode.Dismissed -> { + notificationProcessor.processReminderEventsInNotification( + ProcessedNotificationData.fromBundle(intent.extras!!), + ReminderEvent.ReminderStatus.SKIPPED + ) + scheduleNextReminderNotificationProcessor.scheduleNextReminder() + } + + ProcessorCode.Taken -> { + notificationProcessor.processReminderEventsInNotification( + ProcessedNotificationData.fromBundle(intent.extras!!), + ReminderEvent.ReminderStatus.TAKEN + ) + scheduleNextReminderNotificationProcessor.scheduleNextReminder() + } + + ProcessorCode.Acknowledged -> { + notificationProcessor.processReminderEventsInNotification( + ProcessedNotificationData.fromBundle(intent.extras!!), + ReminderEvent.ReminderStatus.ACKNOWLEDGED + ) + scheduleNextReminderNotificationProcessor.scheduleNextReminder() + } ProcessorCode.Snooze -> processSnooze(intent) - ProcessorCode.Reminder -> reminderNotificationProcessor.processReminders(ReminderNotificationData.fromBundle(intent.extras!!)) + ProcessorCode.Reminder -> { + if (reminderNotificationProcessor.processReminders(ReminderNotificationData.fromBundle(intent.extras ?: Bundle()))) { + scheduleNextReminderNotificationProcessor.scheduleNextReminder() + } + } + ProcessorCode.ShowReminderNotification -> showReminderNotificationProcessor.showReminder( ReminderNotificationData.fromBundle(intent.extras!!) ) @@ -86,7 +104,7 @@ class ReminderProcessorBroadcastReceiver : BroadcastReceiver() { ProcessorCode.Refill -> processRefill(intent) ProcessorCode.StockHandling -> processStockHandling(intent) ProcessorCode.Schedule -> scheduleNextReminderNotificationProcessor.scheduleNextReminder() - ProcessorCode.LocationSnooze -> snoozeProcessor.processLocationSnooze(ReminderNotificationData.fromBundle(intent.extras!!)) + ProcessorCode.LocationSnooze -> snoozeProcessor.processLocationSnooze(ReminderNotificationData.fromBundle(intent.extras ?: Bundle())) } } finally { pendingResult.finish() @@ -102,7 +120,7 @@ class ReminderProcessorBroadcastReceiver : BroadcastReceiver() { } } - private fun processSnooze(intent: Intent) { + private suspend fun processSnooze(intent: Intent) { snoozeProcessor.processSnooze( ReminderNotificationData.fromBundle(intent.extras!!), intent.getLongExtra(ActivityCodes.EXTRA_SNOOZE_TIME_SECONDS, 0).toDuration(DurationUnit.SECONDS) diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/ScheduleNextReminderNotificationProcessor.kt b/app/src/main/java/com/futsch1/medtimer/reminders/ScheduleNextReminderNotificationProcessor.kt index 89d72260b..d6a90a9fe 100644 --- a/app/src/main/java/com/futsch1/medtimer/reminders/ScheduleNextReminderNotificationProcessor.kt +++ b/app/src/main/java/com/futsch1/medtimer/reminders/ScheduleNextReminderNotificationProcessor.kt @@ -4,48 +4,44 @@ import android.util.Log import com.futsch1.medtimer.LogTags import com.futsch1.medtimer.database.MedicineRepository import com.futsch1.medtimer.database.ReminderEventRepository -import com.futsch1.medtimer.model.Medicine -import com.futsch1.medtimer.model.ReminderEvent -import com.futsch1.medtimer.model.ScheduledReminder import com.futsch1.medtimer.preferences.PreferencesDataSource import com.futsch1.medtimer.reminders.notificationData.ReminderNotificationData import com.futsch1.medtimer.reminders.scheduling.ReminderScheduler +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import javax.inject.Inject +import javax.inject.Singleton +@Singleton class ScheduleNextReminderNotificationProcessor @Inject constructor( private val alarmProcessor: AlarmProcessor, + private val reminderNotificationProcessor: ReminderNotificationProcessor, private val medicineRepository: MedicineRepository, private val reminderEventRepository: ReminderEventRepository, private val timeAccess: TimeAccess, private val preferencesDataSource: PreferencesDataSource ) { + private val mutex = Mutex() - suspend fun scheduleNextReminder(processedEvents: List = emptyList()) { - val medicines = medicineRepository.getAll() - val reminderEvents = reminderEventRepository.getForScheduling(medicines) - val allEvents = (reminderEvents + processedEvents).distinctBy { it.reminderEventId } + suspend fun scheduleNextReminder() { + mutex.withLock { + val medicines = medicineRepository.getAll() + val reminderEvents = reminderEventRepository.getForScheduling(medicines) + Log.d(LogTags.REMINDER, "Schedule next reminders, considering events ${reminderEvents.map { it.reminderEventId }}") - scheduleNextReminderInternal(medicines, allEvents) - } + val scheduledReminders = ReminderScheduler(timeAccess, preferencesDataSource).schedule(medicines, reminderEvents) + if (scheduledReminders.isEmpty()) { + Log.d(LogTags.REMINDER, "No reminders scheduled") + alarmProcessor.cancelNextReminder() + return + } + + val data = ReminderNotificationData.fromScheduledReminders( + if (preferencesDataSource.preferences.value.combineNotifications) scheduledReminders + else listOf(scheduledReminders[0]) + ) - private fun scheduleNextReminderInternal( - medicines: List, - reminderEvents: List - ) { - val reminderScheduler = ReminderScheduler(timeAccess, preferencesDataSource) - val scheduledReminders: List = - reminderScheduler.schedule(medicines, reminderEvents) - if (scheduledReminders.isNotEmpty()) { - val scheduledReminderNotificationData = - ReminderNotificationData.fromScheduledReminders( - if (preferencesDataSource.preferences.value.combineNotifications) scheduledReminders else listOf( - scheduledReminders[0] - ) - ) - alarmProcessor.setAlarmForReminderNotification(scheduledReminderNotificationData) - } else { - Log.d(LogTags.REMINDER, "No reminders scheduled") - alarmProcessor.cancelNextReminder() + alarmProcessor.setAlarmForReminderNotification(data, reminderNotificationProcessor) } } } diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/ShowReminderNotificationProcessor.kt b/app/src/main/java/com/futsch1/medtimer/reminders/ShowReminderNotificationProcessor.kt index 22a5ad8b5..e4fdbc756 100644 --- a/app/src/main/java/com/futsch1/medtimer/reminders/ShowReminderNotificationProcessor.kt +++ b/app/src/main/java/com/futsch1/medtimer/reminders/ShowReminderNotificationProcessor.kt @@ -1,9 +1,11 @@ package com.futsch1.medtimer.reminders import android.app.NotificationManager +import android.content.Context import android.util.Log import com.futsch1.medtimer.LogTags import com.futsch1.medtimer.reminders.notificationData.ReminderNotificationData +import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject /** @@ -14,8 +16,8 @@ import javax.inject.Inject * the actual notification scheduling to [AlarmProcessor]. */ class ShowReminderNotificationProcessor @Inject constructor( + @param:ApplicationContext private val context: Context, private val alarmProcessor: AlarmProcessor, - private val scheduleNextReminderNotificationProcessor: ScheduleNextReminderNotificationProcessor, private val notificationProcessor: NotificationProcessor, private val notificationManager: NotificationManager ) { @@ -26,8 +28,6 @@ class ShowReminderNotificationProcessor @Inject constructor( if (!isNotificationActive(reminderNotificationData)) { alarmProcessor.setAlarmForReminderNotification(reminderNotificationData) } - - scheduleNextReminderNotificationProcessor.scheduleNextReminder() } private suspend fun isNotificationActive(reminderNotificationData: ReminderNotificationData): Boolean { diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/SnoozeProcessor.kt b/app/src/main/java/com/futsch1/medtimer/reminders/SnoozeProcessor.kt index 6a70ae2a9..2c48217c1 100644 --- a/app/src/main/java/com/futsch1/medtimer/reminders/SnoozeProcessor.kt +++ b/app/src/main/java/com/futsch1/medtimer/reminders/SnoozeProcessor.kt @@ -24,7 +24,7 @@ open class SnoozeProcessor @Inject constructor( private val geofenceRegistrar: GeofenceRegistrar ) { - fun processSnooze(reminderNotificationData: ReminderNotificationData, snoozeTime: Duration) { + suspend fun processSnooze(reminderNotificationData: ReminderNotificationData, snoozeTime: Duration) { reminderNotificationData.remindInstant = Instant.now().plusSeconds(snoozeTime.inWholeSeconds) Log.d(LogTags.REMINDER, "Snoozing reminder: $reminderNotificationData") diff --git a/app/src/main/java/com/futsch1/medtimer/reminders/notificationData/ReminderNotificationFactory.kt b/app/src/main/java/com/futsch1/medtimer/reminders/notificationData/ReminderNotificationFactory.kt index fd4e8f19e..e122d4f27 100644 --- a/app/src/main/java/com/futsch1/medtimer/reminders/notificationData/ReminderNotificationFactory.kt +++ b/app/src/main/java/com/futsch1/medtimer/reminders/notificationData/ReminderNotificationFactory.kt @@ -52,6 +52,7 @@ open class ReminderNotificationFactory @Inject constructor( reminderNotificationData.remindInstant.epochSecond, medicine, reminder, reminderEventRepository, timeFormatter ) reminderEvent = reminderEventRepository.create(newEvent.copy(remainingRepeats = numberOfRepeats)) + Log.d(LogTags.REMINDER, "Created reminder event rEID [${reminderEvent.reminderEventId}] for reminder rID [${reminder.id}]") } else { reminderNotificationData.notificationId = reminderEvent.notificationId } diff --git a/app/src/main/java/com/futsch1/medtimer/statistics/ChartsFragment.kt b/app/src/main/java/com/futsch1/medtimer/statistics/ChartsFragment.kt index 58f3dc37a..88afc1816 100644 --- a/app/src/main/java/com/futsch1/medtimer/statistics/ChartsFragment.kt +++ b/app/src/main/java/com/futsch1/medtimer/statistics/ChartsFragment.kt @@ -327,7 +327,11 @@ class ChartsFragment : Fragment() { viewModel.setDays(viewModel.uiState.value?.days ?: (arguments?.getInt(DAYS_BUNDLE_KEY) ?: 0)) } - fun setDays(days: Int) = viewModel.setDays(days) + fun setDays(days: Int) { + if (isAdded) { + viewModel.setDays(days) + } + } private inner class DaysSinceEpochFormat : NumberFormat() { override fun format( diff --git a/app/src/test/java/com/futsch1/medtimer/location/LocationSnoozeProcessorTest.kt b/app/src/test/java/com/futsch1/medtimer/location/LocationSnoozeProcessorTest.kt index 44959ec92..4909f826c 100644 --- a/app/src/test/java/com/futsch1/medtimer/location/LocationSnoozeProcessorTest.kt +++ b/app/src/test/java/com/futsch1/medtimer/location/LocationSnoozeProcessorTest.kt @@ -4,10 +4,12 @@ import com.futsch1.medtimer.preferences.PersistentDataDataSource import com.futsch1.medtimer.reminders.AlarmProcessor import com.futsch1.medtimer.reminders.LocationSnoozeProcessor import com.futsch1.medtimer.reminders.notificationData.ReminderNotificationData +import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any +import org.mockito.kotlin.isNull import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.times @@ -37,9 +39,9 @@ class LocationSnoozeProcessorTest { fun emptyPendingList() { whenever(persistentDataDataSource.getPendingLocationSnoozes()).thenReturn(emptyList()) - processor.processLocationSnooze() + runBlocking { processor.processLocationSnooze() } - verify(alarmProcessor, never()).setAlarmForReminderNotification(any()) + runBlocking { verify(alarmProcessor, never()).setAlarmForReminderNotification(any(), isNull()) } verify(persistentDataDataSource).clearAllPendingLocationSnoozes() verify(geofenceRegistrar).unregisterHomeGeofence() } @@ -50,9 +52,9 @@ class LocationSnoozeProcessorTest { val data = ReminderNotificationData(futureInstant, listOf(1), mutableListOf(10), 1) whenever(persistentDataDataSource.getPendingLocationSnoozes()).thenReturn(listOf(data)) - processor.processLocationSnooze() + runBlocking { processor.processLocationSnooze() } - verify(alarmProcessor, times(1)).setAlarmForReminderNotification(any()) + runBlocking { verify(alarmProcessor, times(1)).setAlarmForReminderNotification(any(), isNull()) } verify(persistentDataDataSource).clearAllPendingLocationSnoozes() verify(geofenceRegistrar).unregisterHomeGeofence() } @@ -66,9 +68,9 @@ class LocationSnoozeProcessorTest { ) whenever(persistentDataDataSource.getPendingLocationSnoozes()).thenReturn(snoozes) - processor.processLocationSnooze() + runBlocking { processor.processLocationSnooze() } - verify(alarmProcessor, times(3)).setAlarmForReminderNotification(any()) + runBlocking { verify(alarmProcessor, times(3)).setAlarmForReminderNotification(any(), isNull()) } verify(geofenceRegistrar).unregisterHomeGeofence() } } diff --git a/app/src/test/java/com/futsch1/medtimer/processortests/ShowReminderNotificationProcessorTest.kt b/app/src/test/java/com/futsch1/medtimer/processortests/ShowReminderNotificationProcessorTest.kt index 3ba0558bc..50151c98e 100644 --- a/app/src/test/java/com/futsch1/medtimer/processortests/ShowReminderNotificationProcessorTest.kt +++ b/app/src/test/java/com/futsch1/medtimer/processortests/ShowReminderNotificationProcessorTest.kt @@ -34,6 +34,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.anyInt +import org.mockito.ArgumentMatchers.anyLong import org.mockito.ArgumentMatchers.eq import org.mockito.Mockito.never import org.mockito.Mockito.times @@ -139,8 +140,6 @@ class ShowReminderNotificationProcessorTest { // The actually requested reminder verify(reminderContext.alarmManagerMock, times(1)).setAndAllowWhileIdle(anyInt(), eq(10_000L), any()) - // And the one for tomorrow - verify(reminderContext.alarmManagerMock, times(1)).setAndAllowWhileIdle(anyInt(), eq(24 * 60 * 60 * 1000L + 10 * 60 * 60 * 1000L), any()) } @Test @@ -160,10 +159,8 @@ class ShowReminderNotificationProcessorTest { verify(reminderContext.notificationManagerFake.mock, never()).cancel(anyInt()) // Never raise a new one verify(reminderContext.notificationManagerFake.mock, never()).notify(anyInt(), any()) - // The actually requested reminder - verify(reminderContext.alarmManagerMock, never()).setAndAllowWhileIdle(anyInt(), eq(10_000L), any()) - // And the one for tomorrow - verify(reminderContext.alarmManagerMock, times(1)).setAndAllowWhileIdle(anyInt(), eq(24 * 60 * 60 * 1000L + 10 * 60 * 60 * 1000L), any()) + // No alarm set when notification is already active + verify(reminderContext.alarmManagerMock, never()).setAndAllowWhileIdle(anyInt(), anyLong(), any()) } @Test @@ -180,13 +177,11 @@ class ShowReminderNotificationProcessorTest { ) } - // Send broadcast (one for the reminder and one for updating the widget) + // Send broadcast for the reminder val broadcastIntents = shadowOf(ApplicationProvider.getApplicationContext()).broadcastIntents - assertEquals(2, broadcastIntents.size) + assertEquals(1, broadcastIntents.size) // The actually requested reminder verify(reminderContext.alarmManagerMock, never()).setAndAllowWhileIdle(anyInt(), eq(10_000L), any()) - // And two times for tomorrow (twice is actually unnecessary, but to reduce complexity, scheduling is called more often) - verify(reminderContext.alarmManagerMock, times(1)).setAndAllowWhileIdle(anyInt(), eq(24 * 60 * 60 * 1000L + 10 * 60 * 60 * 1000L), any()) } @Test diff --git a/app/src/testFull/java/com/futsch1/medtimer/location/GeofenceBroadcastReceiverTest.kt b/app/src/testFull/java/com/futsch1/medtimer/location/GeofenceBroadcastReceiverTest.kt index 6c7b501c9..05591e457 100644 --- a/app/src/testFull/java/com/futsch1/medtimer/location/GeofenceBroadcastReceiverTest.kt +++ b/app/src/testFull/java/com/futsch1/medtimer/location/GeofenceBroadcastReceiverTest.kt @@ -3,6 +3,9 @@ package com.futsch1.medtimer.location import com.futsch1.medtimer.reminders.LocationSnoozeProcessor import com.google.android.gms.location.Geofence import com.google.android.gms.location.GeofencingEvent +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -24,6 +27,7 @@ class GeofenceBroadcastReceiverTest { locationSnoozeProcessor = mock() receiver = GeofenceBroadcastReceiver() receiver.locationSnoozeProcessor = locationSnoozeProcessor + receiver.applicationScope = CoroutineScope(Dispatchers.Unconfined) } @Test @@ -34,7 +38,7 @@ class GeofenceBroadcastReceiverTest { receiver.handleGeofencingEvent(event) - verify(locationSnoozeProcessor).processLocationSnooze() + runBlocking { verify(locationSnoozeProcessor).processLocationSnooze() } } @Test @@ -45,7 +49,7 @@ class GeofenceBroadcastReceiverTest { receiver.handleGeofencingEvent(event) - verify(locationSnoozeProcessor, never()).processLocationSnooze() + runBlocking { verify(locationSnoozeProcessor, never()).processLocationSnooze() } } @Test @@ -56,6 +60,6 @@ class GeofenceBroadcastReceiverTest { receiver.handleGeofencingEvent(event) - verify(locationSnoozeProcessor, never()).processLocationSnooze() + runBlocking { verify(locationSnoozeProcessor, never()).processLocationSnooze() } } }