Properly handle exact alarms

- Use `USE_EXACT_ALARM` permission on API 33 and above
 - Degrade to `setAndAllowWhileIdle` just in case `canScheduleExactAlarms()` returns false on some wierd device
This commit is contained in:
Naveen 2023-09-05 12:28:47 +05:30
parent 12837680e1
commit dc81fddd05
No known key found for this signature in database
GPG Key ID: 0E155DAD31671DA3
2 changed files with 30 additions and 25 deletions

View File

@ -9,10 +9,13 @@
<uses-permission android:name="android.permission.READ_CALENDAR" /> <uses-permission android:name="android.permission.READ_CALENDAR" />
<uses-permission android:name="android.permission.WRITE_CALENDAR" /> <uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" /> <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission
android:name="android.permission.SCHEDULE_EXACT_ALARM"
android:maxSdkVersion="32" />
<uses-permission <uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" /> android:maxSdkVersion="28" />

View File

@ -20,7 +20,6 @@ import android.provider.CalendarContract
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.core.app.AlarmManagerCompat
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.print.PrintHelper import androidx.print.PrintHelper
import com.simplemobiletools.calendar.pro.R import com.simplemobiletools.calendar.pro.R
@ -136,28 +135,24 @@ fun Context.scheduleNextEventReminder(event: Event, showToasts: Boolean) {
} }
} }
fun Context.scheduleEventIn(notifTS: Long, event: Event, showToasts: Boolean) { fun Context.scheduleEventIn(notifyAtMillis: Long, event: Event, showToasts: Boolean) {
if (notifTS < System.currentTimeMillis()) { val now = System.currentTimeMillis()
if (notifyAtMillis < now) {
if (showToasts) { if (showToasts) {
toast(com.simplemobiletools.commons.R.string.saving) toast(com.simplemobiletools.commons.R.string.saving)
} }
return return
} }
val newNotifTS = notifTS + 1000 val newNotifyAtMillis = notifyAtMillis + 1000
if (showToasts) { if (showToasts) {
val secondsTillNotification = (newNotifTS - System.currentTimeMillis()) / 1000 val secondsTillNotification = (newNotifyAtMillis - now) / 1000
val msg = String.format(getString(com.simplemobiletools.commons.R.string.time_remaining), formatSecondsToTimeString(secondsTillNotification.toInt())) val msg = String.format(getString(com.simplemobiletools.commons.R.string.time_remaining), formatSecondsToTimeString(secondsTillNotification.toInt()))
toast(msg) toast(msg)
} }
val pendingIntent = getNotificationIntent(event) val pendingIntent = getNotificationIntent(event)
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager setExactAlarm(newNotifyAtMillis, pendingIntent)
try {
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, newNotifTS, pendingIntent)
} catch (e: Exception) {
showErrorToast(e)
}
} }
// hide the actual notification from the top bar // hide the actual notification from the top bar
@ -186,19 +181,11 @@ fun Context.scheduleNextAutomaticBackup() {
if (config.autoBackup) { if (config.autoBackup) {
val backupAtMillis = getNextAutoBackupTime().millis val backupAtMillis = getNextAutoBackupTime().millis
val pendingIntent = getAutomaticBackupIntent() val pendingIntent = getAutomaticBackupIntent()
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager setExactAlarm(backupAtMillis, pendingIntent)
try {
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.RTC_WAKEUP, backupAtMillis, pendingIntent)
} catch (e: Exception) {
showErrorToast(e)
}
} }
} }
fun Context.cancelScheduledAutomaticBackup() { fun Context.cancelScheduledAutomaticBackup() = getAlarmManager().cancel(getAutomaticBackupIntent())
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmManager.cancel(getAutomaticBackupIntent())
}
fun Context.checkAndBackupEventsOnBoot() { fun Context.checkAndBackupEventsOnBoot() {
if (config.autoBackup) { if (config.autoBackup) {
@ -568,13 +555,13 @@ fun Context.scheduleCalDAVSync(activate: Boolean) {
syncIntent, syncIntent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
) )
val alarm = getSystemService(Context.ALARM_SERVICE) as AlarmManager val alarmManager = getAlarmManager()
alarm.cancel(pendingIntent) alarmManager.cancel(pendingIntent)
if (activate) { if (activate) {
val syncCheckInterval = 2 * AlarmManager.INTERVAL_HOUR val syncCheckInterval = 2 * AlarmManager.INTERVAL_HOUR
try { try {
alarm.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + syncCheckInterval, syncCheckInterval, pendingIntent) alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + syncCheckInterval, syncCheckInterval, pendingIntent)
} catch (ignored: Exception) { } catch (ignored: Exception) {
} }
} }
@ -917,3 +904,18 @@ fun Context.addImportIdsToTasks(callback: () -> Unit) {
} }
} }
} }
fun Context.getAlarmManager() = getSystemService(Context.ALARM_SERVICE) as AlarmManager
fun Context.setExactAlarm(triggerAtMillis: Long, operation: PendingIntent, type: Int = AlarmManager.RTC_WAKEUP) {
val alarmManager = getAlarmManager()
try {
if (isSPlus() && alarmManager.canScheduleExactAlarms() || !isSPlus()) {
alarmManager.setExactAndAllowWhileIdle(type, triggerAtMillis, operation)
} else {
alarmManager.setAndAllowWhileIdle(type, triggerAtMillis, operation)
}
} catch (e: Exception) {
showErrorToast(e)
}
}