forked from ankidroid/Anki-Android
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add WidgetAlarm for managing recurring widget updates
- Introduced `WidgetAlarm` object to handle the setting and cancellation of recurring alarms for widget updates. - Added methods to create or retrieve `PendingIntent` instances associated with widgets. - Ensured that alarms are set to trigger widget updates every minute, avoiding multiple alarms for the same widget. - Integrated logging with Timber for tracking alarm creation and cancellation.
- Loading branch information
Showing
2 changed files
with
121 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
AnkiDroid/src/main/java/com/ichi2/widget/WidgetAlarm.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/* | ||
* Copyright (c) 2024 Anoop <[email protected]> | ||
* | ||
* This program is free software; you can redistribute it and/or modify it under | ||
* the terms of the GNU General Public License as published by the Free Software | ||
* Foundation; either version 3 of the License, or (at your option) any later | ||
* version. | ||
* | ||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
* PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License along with | ||
* this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package com.ichi2.widget | ||
|
||
import android.app.AlarmManager | ||
import android.app.PendingIntent | ||
import android.appwidget.AppWidgetManager | ||
import android.content.Context | ||
import android.content.Intent | ||
import android.os.SystemClock | ||
import timber.log.Timber | ||
import kotlin.time.Duration.Companion.seconds | ||
|
||
object WidgetAlarm { | ||
|
||
/** | ||
* Provides the AlarmManager instance. | ||
* | ||
* @param context the context of the application | ||
* @return the AlarmManager instance | ||
*/ | ||
private fun alarmManager(context: Context): AlarmManager { | ||
return context.getSystemService(Context.ALARM_SERVICE) as AlarmManager | ||
} | ||
|
||
/** | ||
* Retrieves or creates a PendingIntent for the widget. | ||
* | ||
* @param context the context of the application | ||
* @param appWidgetId the ID of the widget | ||
* @param create whether to create a new PendingIntent or just retrieve it | ||
* @return the PendingIntent for the widget | ||
*/ | ||
private fun getPendingIntent( | ||
context: Context, | ||
appWidgetId: AppWidgetId, | ||
create: Boolean | ||
): PendingIntent? { | ||
val intent = Intent(context, DeckPickerWidget::class.java).apply { | ||
action = DeckPickerWidget.ACTION_UPDATE_WIDGET | ||
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) | ||
} | ||
return PendingIntent.getBroadcast( | ||
context, | ||
appWidgetId, | ||
intent, | ||
if (create) { | ||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE | ||
} else { | ||
PendingIntent.FLAG_NO_CREATE or PendingIntent.FLAG_IMMUTABLE | ||
} | ||
) | ||
} | ||
|
||
/** | ||
* Ensure a recurring alarm is set to update the widget every minute. | ||
* | ||
* If the alarm is already set for the widget, this method does nothing. | ||
* This ensures that multiple alarms are not created for the same widget, | ||
* preventing potential performance issues or unexpected behavior. | ||
* | ||
* @param context the context of the application | ||
* @param appWidgetId the ID of the widget | ||
*/ | ||
fun setRecurringAlarm(context: Context, appWidgetId: AppWidgetId) { | ||
val pendingIntent = getPendingIntent(context, appWidgetId, create = false) | ||
|
||
if (pendingIntent != null) { | ||
Timber.v("Recurring alarm PendingIntent already exists for widget ID: $appWidgetId") | ||
return | ||
} | ||
|
||
Timber.v("Creating a new recurring alarm PendingIntent for widget ID: $appWidgetId") | ||
|
||
val alarmManager = alarmManager(context) | ||
val newPendingIntent = getPendingIntent(context, appWidgetId, create = true) | ||
|
||
// Set alarm to trigger every minute | ||
val ONE_MINUTE_MILLIS = 60.seconds.inWholeMilliseconds | ||
if (newPendingIntent != null) { | ||
alarmManager.setRepeating( | ||
AlarmManager.ELAPSED_REALTIME, | ||
SystemClock.elapsedRealtime() + ONE_MINUTE_MILLIS, | ||
ONE_MINUTE_MILLIS, | ||
newPendingIntent | ||
) | ||
} | ||
} | ||
|
||
/** | ||
* Cancels the recurring alarm for the widget. | ||
* | ||
* @param context the context of the application | ||
* @param appWidgetId the ID of the widget | ||
*/ | ||
fun cancelRecurringAlarm(context: Context, appWidgetId: AppWidgetId) { | ||
val pendingIntent = getPendingIntent(context, appWidgetId, create = true) | ||
val alarmManager = alarmManager(context) | ||
Timber.d("Canceling recurring alarm for widget ID: $appWidgetId") | ||
if (pendingIntent != null) { | ||
alarmManager.cancel(pendingIntent) | ||
} | ||
} | ||
} |