diff --git a/onebusaway-android/src/main/AndroidManifest.xml b/onebusaway-android/src/main/AndroidManifest.xml index 594a251c2..98ace5da4 100644 --- a/onebusaway-android/src/main/AndroidManifest.xml +++ b/onebusaway-android/src/main/AndroidManifest.xml @@ -45,6 +45,8 @@ + + = Build.VERSION_CODES.M) { + alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerTime, alarmIntent); + } + } + + private static PendingIntent createAlarmIntent(Context context, Uri alertUri) { + Intent intent = new Intent(TripService.ACTION_POLL, alertUri, context, AlarmReceiver.class); + int flags; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { flags = PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE; } else { flags = PendingIntent.FLAG_ONE_SHOT; } - PendingIntent alarmIntent = PendingIntent.getBroadcast(context, 0, - intent, flags); - AlarmManager alarm = - (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - // Try to cut through Doze so alarm still triggers - See #558 - // Note that we intentionally do NOT use alarm.setAlarmClock() because this creates - // an alarm in the user's status bar and notification drawer which can be annoying - see - // https://stackoverflow.com/questions/34699662/how-does-alarmmanager-alarmclockinfos-pendingintent-work - alarm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerTime, alarmIntent); - } else { - alarm.set(AlarmManager.RTC_WAKEUP, triggerTime, alarmIntent); - } + return PendingIntent.getBroadcast(context, 0, intent, flags); } public static void notifyTrip(Context context, Uri alertUri, String notifyTitle, String notifyText) { diff --git a/onebusaway-android/src/main/java/org/onebusaway/android/ui/TripInfoActivity.java b/onebusaway-android/src/main/java/org/onebusaway/android/ui/TripInfoActivity.java index c19655209..19e6a7fe7 100644 --- a/onebusaway-android/src/main/java/org/onebusaway/android/ui/TripInfoActivity.java +++ b/onebusaway-android/src/main/java/org/onebusaway/android/ui/TripInfoActivity.java @@ -15,6 +15,8 @@ */ package org.onebusaway.android.ui; +import android.Manifest; +import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.ContentResolver; @@ -25,7 +27,9 @@ import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.provider.Settings; import android.text.format.DateUtils; import android.util.Log; import android.view.LayoutInflater; @@ -50,6 +54,7 @@ import java.util.List; import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; @@ -57,6 +62,8 @@ import androidx.loader.content.CursorLoader; import androidx.loader.content.Loader; +import static org.onebusaway.android.util.PermissionUtils.NOTIFICATION_PERMISSION_REQUEST; + public class TripInfoActivity extends AppCompatActivity { private static final String TAG = "TripInfoActivity"; @@ -415,6 +422,19 @@ public void saveTrip() { // Reminder time // Repeats // + + // Make sure that the user has granted permission for notifications + // and exact alarms. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + if (!TripService.canScheduleExactAlarms(getActivity())) { + showRequestAlarmsPermissionDialog(getActivity()); + return; + } + ActivityCompat.requestPermissions(this.getActivity(), + new String[] {Manifest.permission.POST_NOTIFICATIONS}, + NOTIFICATION_PERMISSION_REQUEST); + } + View view = getView(); final Spinner reminderView = (Spinner) view.findViewById(R.id.trip_info_reminder_time); final TextView nameView = (TextView) view.findViewById(R.id.name); @@ -455,6 +475,27 @@ public void saveTrip() { finish(); } + private void showRequestAlarmsPermissionDialog(Context context) { + AlertDialog.Builder builder = new AlertDialog.Builder(context) + .setTitle(R.string.trip_info_grant_exact_alarms_permission_title) + .setCancelable(true) + .setMessage(R.string.trip_info_grant_exact_alarms_permission_message) + .setPositiveButton( + R.string.trip_info_grant_exact_alarms_permission_positive_button, + (dialog, which) -> { + TripService.requestScheduleExactAlarmsPermission(context); + dialog.dismiss(); + } + ) + .setNegativeButton( + R.string.trip_info_grant_exact_alarms_permission_negative_button, + (dialog, which) -> { + dialog.dismiss(); + }); + AlertDialog alertDialog = builder.create(); + alertDialog.show(); + } + void showReminderDaysDialog() { final boolean[] checks = ObaContract.Trips.daysToArray(mReminderDays); Bundle args = new Bundle(); diff --git a/onebusaway-android/src/main/java/org/onebusaway/android/util/PermissionUtils.java b/onebusaway-android/src/main/java/org/onebusaway/android/util/PermissionUtils.java index 2e4fc5182..b7a809cd7 100644 --- a/onebusaway-android/src/main/java/org/onebusaway/android/util/PermissionUtils.java +++ b/onebusaway-android/src/main/java/org/onebusaway/android/util/PermissionUtils.java @@ -30,6 +30,7 @@ public class PermissionUtils { public static final int SAVE_BACKUP_PERMISSION_REQUEST = 2; public static final int RESTORE_BACKUP_PERMISSION_REQUEST = 3; public static final int BACKGROUND_LOCATION_PERMISSION_REQUEST = 4; + public static final int NOTIFICATION_PERMISSION_REQUEST = 5; public static final String[] LOCATION_PERMISSIONS = { Manifest.permission.ACCESS_FINE_LOCATION, diff --git a/onebusaway-android/src/main/res/values-es/strings.xml b/onebusaway-android/src/main/res/values-es/strings.xml index 06cabef9d..70ed0cda6 100644 --- a/onebusaway-android/src/main/res/values-es/strings.xml +++ b/onebusaway-android/src/main/res/values-es/strings.xml @@ -1047,4 +1047,8 @@ Bicicleta Compartida Toca para reservar una bicicleta Toca para reservar esta bicicleta + Se requiere permiso + Debes otorgar permiso a la aplicación para programar un recordatorio. + Otorgar permiso + Cancelar diff --git a/onebusaway-android/src/main/res/values-fi/strings.xml b/onebusaway-android/src/main/res/values-fi/strings.xml index a3a2e1820..3280a3483 100644 --- a/onebusaway-android/src/main/res/values-fi/strings.xml +++ b/onebusaway-android/src/main/res/values-fi/strings.xml @@ -631,4 +631,8 @@ (https://github.com/google/material-design-icons), " "licensed under Apache v2.0 (https://www.apache.org/licenses/LICENSE-2.0).\n\n" + Lupa tarvitaan + Sinun täytyy antaa sovellukselle lupa muistutuksen asettamiseen. + Myönnä lupa + Peruuta diff --git a/onebusaway-android/src/main/res/values-it/strings.xml b/onebusaway-android/src/main/res/values-it/strings.xml index 9035d4119..3eaeda59c 100644 --- a/onebusaway-android/src/main/res/values-it/strings.xml +++ b/onebusaway-android/src/main/res/values-it/strings.xml @@ -909,4 +909,8 @@ Rifiutare partecipazione alla ricerca? Se scegli di non partecipare alla ricerca non riceveremo più informazioni riguardo alle tue abitudini di viaggio per migliorare il servizio di trasporto pubblico. Annulla + Permesso necessario + Devi concedere all\'app il permesso di pianificare un promemoria. + Concedi il permesso + Annulla \ No newline at end of file diff --git a/onebusaway-android/src/main/res/values/strings.xml b/onebusaway-android/src/main/res/values/strings.xml index e688d0d99..183fda956 100644 --- a/onebusaway-android/src/main/res/values/strings.xml +++ b/onebusaway-android/src/main/res/values/strings.xml @@ -450,6 +450,10 @@ Show Route Show Stop - + Permission Needed + You must grant the app permission to schedule a reminder. + Grant Permission + Cancel Historically full