Skip to content
Merged
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
Expand Up @@ -16,8 +16,8 @@
package com.ichi2.anki.tests

import android.app.NotificationManager
import android.content.Context
import android.os.Build
import androidx.core.content.getSystemService
import androidx.test.annotation.UiThreadTest
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
Expand Down Expand Up @@ -54,7 +54,7 @@ class NotificationChannelTest : InstrumentedTest() {
(targetContext.applicationContext as AnkiDroidApp).onCreate()
currentAPI = sdkVersion
targetAPI = targetContext.applicationInfo.targetSdkVersion
manager = targetContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager = targetContext.getSystemService<NotificationManager>()!!
}

private fun channelsInAPI(): Boolean = currentAPI >= 26
Expand Down
5 changes: 5 additions & 0 deletions AnkiDroid/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,11 @@
android:enabled="true"
android:exported="false"
/>
<receiver
android:name=".services.AlarmManagerService"
android:enabled="true"
android:exported="false"
/>
<receiver
android:name=".services.BootService"
android:enabled="true"
Expand Down
3 changes: 2 additions & 1 deletion AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import com.ichi2.anki.preferences.SharedPreferencesProvider
import com.ichi2.anki.preferences.sharedPrefs
import com.ichi2.anki.servicelayer.DebugInfoService
import com.ichi2.anki.servicelayer.ThrowableFilterService
import com.ichi2.anki.services.AlarmManagerService
import com.ichi2.anki.services.NotificationService
import com.ichi2.anki.settings.Prefs
import com.ichi2.anki.ui.dialogs.ActivityAgnosticDialogs
Expand Down Expand Up @@ -206,7 +207,7 @@ open class AnkiDroidApp :

if (Prefs.newReviewRemindersEnabled) {
Timber.i("Setting review reminder notifications if they have not already been set")
// TODO: GSoC 2025
AlarmManagerService.scheduleAllNotifications(applicationContext)
} else {
// Register for notifications
Timber.i("AnkiDroidApp: Starting Services")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import com.google.android.material.appbar.CollapsingToolbarLayout
import com.google.android.material.appbar.MaterialToolbar
import com.ichi2.anki.R
import com.ichi2.anki.SingleFragmentActivity
import com.ichi2.anki.common.annotations.LegacyNotifications
import com.ichi2.anki.preferences.HeaderFragment.Companion.getHeaderKeyForFragment
import com.ichi2.anki.reviewreminders.ReviewReminderScope
import com.ichi2.anki.reviewreminders.ScheduleReminders
Expand Down Expand Up @@ -260,6 +261,7 @@ class PreferencesActivity :
}

// Only enable AnkiDroid notifications unrelated to due reminders
@LegacyNotifications("Magic number which is no longer needed")
const val PENDING_NOTIFICATIONS_ONLY = 1000000

const val INITIAL_FRAGMENT_EXTRA = "initial_fragment"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import kotlin.time.Duration.Companion.minutes
@Serializable
@Parcelize
value class ReviewReminderId(
val id: Int,
val value: Int,
) : Parcelable {
companion object {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import com.ichi2.anki.dialogs.DeckSelectionDialog
import com.ichi2.anki.launchCatchingTask
import com.ichi2.anki.libanki.DeckId
import com.ichi2.anki.model.SelectableDeck
import com.ichi2.anki.services.AlarmManagerService
import com.ichi2.anki.showError
import com.ichi2.anki.snackbar.BaseSnackbarBuilderProvider
import com.ichi2.anki.snackbar.SnackbarBuilder
Expand Down Expand Up @@ -186,6 +187,7 @@ class ScheduleReminders :
Timber.d("Handling add/edit dialog result: mode=%s reminder=%s", modeOfFinishedDialog, newOrModifiedReminder)
updateDatabaseForAddEditDialog(newOrModifiedReminder, modeOfFinishedDialog)
updateUIForAddEditDialog(newOrModifiedReminder, modeOfFinishedDialog)
updateAlarmsForAddEditDialog(newOrModifiedReminder, modeOfFinishedDialog)
// Feedback
showSnackbar(
when (modeOfFinishedDialog) {
Expand Down Expand Up @@ -282,6 +284,28 @@ class ScheduleReminders :
triggerUIUpdate()
}

/**
* Update the AlarmManager notifications for the new or modified reminder.
* @see handleAddEditDialogResult
*/
private fun updateAlarmsForAddEditDialog(
newOrModifiedReminder: ReviewReminder?,
modeOfFinishedDialog: AddEditReminderDialog.DialogMode,
) {
if (modeOfFinishedDialog is AddEditReminderDialog.DialogMode.Edit) {
AlarmManagerService.unscheduleReviewReminderNotifications(
requireContext(),
modeOfFinishedDialog.reminderToBeEdited,
)
}
newOrModifiedReminder?.let {
AlarmManagerService.scheduleReviewReminderNotification(
requireContext(),
it,
)
}
}

/**
* Retrieves a deck name from the collection for a given deck ID and passes it to the provided callback.
* Used by the [ScheduleRemindersAdapter] because it cannot access the collection directly.
Expand Down Expand Up @@ -344,6 +368,12 @@ class ScheduleReminders :
// Update UI
reminder.enabled = newState
triggerUIUpdate()

// Update scheduled AlarmManager notifications
when (newState) {
true -> AlarmManagerService.scheduleReviewReminderNotification(requireContext(), reminder)
false -> AlarmManagerService.unscheduleReviewReminderNotifications(requireContext(), reminder)
}
}

/**
Expand Down
Loading