fix(todo): reminders at the minute on Android 13 on, through USE_EXACT_ALARM (ADR 0033, D31)

SCHEDULE_EXACT_ALARM is off from Android 14 on until the person allows it
in Alarms & reminders, so every reminder was scheduled inexact and could
come minutes late. USE_EXACT_ALARM is granted with the install to an app
reminding of what a person planned, and AlarmManager.canScheduleExactAlarms
(which flutter_local_notifications' canScheduleExactNotifications asks) is
true with it, so reminders are exactAllowWhileIdle. SCHEDULE_EXACT_ALARM
stays for Android 12 and 12L, which don't know the other, up to API 32.

Whats-New: Reminders arrive on the minute.
Whats-New-De: Erinnerungen kommen auf die Minute.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-04 22:35:05 +01:00
commit d49331b210
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64
2 changed files with 50 additions and 5 deletions

View file

@ -3,12 +3,19 @@
<!-- The app talks to its instance: release builds need this too (Flutter's <!-- The app talks to its instance: release builds need this too (Flutter's
template grants it to debug and profile builds only). --> template grants it to debug and profile builds only). -->
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<!-- Tasks' reminders (ADR 0033, D5): shown (POST_NOTIFICATIONS comes with <!-- Tasks' reminders (ADR 0033, D5, D31): shown (POST_NOTIFICATIONS comes
flutter_local_notifications), scheduled again after a restart, and at with flutter_local_notifications, asked once a reminder is planned),
the minute where the person allows exact alarms (Android 14 leaves scheduled again after a restart, and at the minute: from Android 13 on
them off; without, Android may bring a reminder a few minutes late). --> through USE_EXACT_ALARM, granted with the install to an app reminding
of what a person planned; on 12 and 12L, which don't know it, through
SCHEDULE_EXACT_ALARM, granted there unless taken back, and declared up
to API 32 alone (from 14 on it is off until the person allows it in
Alarms & reminders; without exact alarms a reminder may come minutes
late). -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/> <uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"
android:maxSdkVersion="32"/>
<!-- A task's title dictated in quick add (ADR 0033, D29): the microphone, <!-- A task's title dictated in quick add (ADR 0033, D29): the microphone,
asked for once the person taps it, and the device's speech recogniser, asked for once the person taps it, and the device's speech recogniser,
which Android 11 and later only shows the app when it is declared which Android 11 and later only shows the app when it is declared

View file

@ -0,0 +1,38 @@
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
/// Reminders come at the minute on Android (ADR 0033, D31): from Android 13
/// on through `USE_EXACT_ALARM`, granted with the install to an app that
/// reminds of what a person planned; on 12 and 12L, which don't know it,
/// through `SCHEDULE_EXACT_ALARM`, declared up to API 32 alone, so that from
/// 13 on the app holds no permission the person would have to grant in
/// Alarms & reminders.
void main() {
final manifest = File(
'android/app/src/main/AndroidManifest.xml',
).readAsStringSync();
/// The attributes of each `<uses-permission>` naming [permission].
List<String> declared(String permission) => [
for (final match in RegExp(
'<uses-permission([^>]*android:name="android.permission.$permission"'
'[^>]*)/>',
).allMatches(manifest))
match[1]!,
];
test('USE_EXACT_ALARM is declared, for every version', () {
expect(declared('USE_EXACT_ALARM'), [isNot(contains('maxSdkVersion'))]);
});
test('SCHEDULE_EXACT_ALARM is declared up to Android 12L alone', () {
expect(declared('SCHEDULE_EXACT_ALARM'), [
contains('android:maxSdkVersion="32"'),
]);
});
test('reminders are scheduled again after a restart', () {
expect(declared('RECEIVE_BOOT_COMPLETED'), hasLength(1));
});
}