diff --git a/src/main/java/com/todoroo/andlib/utility/AndroidUtilities.java b/src/main/java/com/todoroo/andlib/utility/AndroidUtilities.java index 2b549dae3..dfef42880 100644 --- a/src/main/java/com/todoroo/andlib/utility/AndroidUtilities.java +++ b/src/main/java/com/todoroo/andlib/utility/AndroidUtilities.java @@ -367,10 +367,18 @@ public class AndroidUtilities { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; } + public static boolean atLeastKitKat() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + } + public static boolean atLeastLollipop() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; } + public static boolean atLeastMarshmallow() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; + } + /** * Sort files by date so the newest file is on top */ diff --git a/src/main/java/com/todoroo/astrid/reminders/ReminderPreferences.java b/src/main/java/com/todoroo/astrid/reminders/ReminderPreferences.java index c25aecd9d..3d4396de2 100644 --- a/src/main/java/com/todoroo/astrid/reminders/ReminderPreferences.java +++ b/src/main/java/com/todoroo/astrid/reminders/ReminderPreferences.java @@ -27,6 +27,7 @@ import org.tasks.ui.TimePreference; import javax.inject.Inject; +import static com.todoroo.andlib.utility.AndroidUtilities.atLeastMarshmallow; import static com.todoroo.andlib.utility.AndroidUtilities.preJellybean; public class ReminderPreferences extends InjectingPreferenceActivity { @@ -38,6 +39,7 @@ public class ReminderPreferences extends InjectingPreferenceActivity { public static String RESET_GEOFENCES = "reset_geofences"; public static String TOGGLE_GEOFENCES = "toggle_geofences"; + public static String RESCHEDULE_ALARMS = "reschedule_alarms"; private Bundle result; @Inject DeviceInfo deviceInfo; @@ -59,6 +61,11 @@ public class ReminderPreferences extends InjectingPreferenceActivity { preferenceScreen.removePreference(findPreference(getString(R.string.p_rmd_notif_actions_enabled))); preferenceScreen.removePreference(findPreference(getString(R.string.p_notification_priority))); } + if (atLeastMarshmallow()) { + setExtraOnChange(R.string.p_doze_notifications, RESCHEDULE_ALARMS); + } else { + preferenceScreen.removePreference(findPreference(getString(R.string.p_doze_notifications))); + } if (deviceInfo.supportsLocationServices()) { setExtraOnChange(R.string.p_geofence_radius, RESET_GEOFENCES); diff --git a/src/main/java/org/tasks/preferences/Preferences.java b/src/main/java/org/tasks/preferences/Preferences.java index 417c6db12..91a8f1b76 100644 --- a/src/main/java/org/tasks/preferences/Preferences.java +++ b/src/main/java/org/tasks/preferences/Preferences.java @@ -29,6 +29,7 @@ import timber.log.Timber; import static android.content.SharedPreferences.Editor; import static com.todoroo.andlib.utility.AndroidUtilities.atLeastJellybean; +import static com.todoroo.andlib.utility.AndroidUtilities.atLeastMarshmallow; public class Preferences { @@ -99,6 +100,10 @@ public class Preferences { return getStringValue(R.string.gcal_p_default); } + public boolean isDozeNotificationEnabled() { + return atLeastMarshmallow() && getBoolean(R.string.p_doze_notifications, false); + } + public boolean geofencesEnabled() { return deviceInfo.supportsLocationServices() && getBoolean(R.string.p_geofence_reminders_enabled, true); } diff --git a/src/main/java/org/tasks/scheduling/AlarmManager.java b/src/main/java/org/tasks/scheduling/AlarmManager.java index 2a48e557b..2f5a6aceb 100644 --- a/src/main/java/org/tasks/scheduling/AlarmManager.java +++ b/src/main/java/org/tasks/scheduling/AlarmManager.java @@ -3,16 +3,22 @@ package org.tasks.scheduling; import android.app.PendingIntent; import android.content.Context; +import org.tasks.R; import org.tasks.injection.ForApplication; +import org.tasks.preferences.Preferences; import javax.inject.Inject; +import static com.todoroo.andlib.utility.AndroidUtilities.atLeastKitKat; + public class AlarmManager { private final android.app.AlarmManager alarmManager; + private final Preferences preferences; @Inject - public AlarmManager(@ForApplication Context context) { + public AlarmManager(@ForApplication Context context, Preferences preferences) { + this.preferences = preferences; alarmManager = (android.app.AlarmManager) context.getSystemService(Context.ALARM_SERVICE); } @@ -21,11 +27,23 @@ public class AlarmManager { } public void wakeup(long time, PendingIntent pendingIntent) { - alarmManager.set(android.app.AlarmManager.RTC_WAKEUP, time, pendingIntent); + if (preferences.isDozeNotificationEnabled()) { + alarmManager.setExactAndAllowWhileIdle(android.app.AlarmManager.RTC_WAKEUP, time, pendingIntent); + } else if (atLeastKitKat()) { + alarmManager.setExact(android.app.AlarmManager.RTC_WAKEUP, time, pendingIntent); + } else { + alarmManager.set(android.app.AlarmManager.RTC_WAKEUP, time, pendingIntent); + } } public void noWakeup(long time, PendingIntent pendingIntent) { - alarmManager.set(android.app.AlarmManager.RTC, time, pendingIntent); + if (preferences.isDozeNotificationEnabled()) { + alarmManager.setExactAndAllowWhileIdle(android.app.AlarmManager.RTC, time, pendingIntent); + } else if (atLeastKitKat()) { + alarmManager.setExact(android.app.AlarmManager.RTC, time, pendingIntent); + } else { + alarmManager.set(android.app.AlarmManager.RTC, time, pendingIntent); + } } public void setInexactRepeating(long interval, PendingIntent pendingIntent) { diff --git a/src/main/java/org/tasks/ui/NavigationDrawerFragment.java b/src/main/java/org/tasks/ui/NavigationDrawerFragment.java index 71a7465f8..db39d18b0 100644 --- a/src/main/java/org/tasks/ui/NavigationDrawerFragment.java +++ b/src/main/java/org/tasks/ui/NavigationDrawerFragment.java @@ -32,6 +32,7 @@ import org.tasks.injection.InjectingFragment; import org.tasks.location.GeofenceService; import org.tasks.preferences.AppearancePreferences; import org.tasks.preferences.Preferences; +import org.tasks.scheduling.AlarmSchedulingIntentService; import javax.inject.Inject; @@ -96,6 +97,9 @@ public class NavigationDrawerFragment extends InjectingFragment { } } else if (data.getBooleanExtra(ReminderPreferences.RESET_GEOFENCES, false)) { geofenceService.setupGeofences(); + } else if (data.getBooleanExtra(ReminderPreferences.RESCHEDULE_ALARMS, false)) { + Context context = getContext(); + context.startService(new Intent(context, AlarmSchedulingIntentService.class)); } if (data.getBooleanExtra(AppearancePreferences.FILTERS_CHANGED, false)) { diff --git a/src/main/res/values/keys.xml b/src/main/res/values/keys.xml index fdca939d3..433fdad91 100644 --- a/src/main/res/values/keys.xml +++ b/src/main/res/values/keys.xml @@ -244,6 +244,7 @@ manual_sort notification_priority disable_notification_light + doze_notifications @string/TEA_ctrl_when_pref diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index b621d459f..27ea105da 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -138,6 +138,9 @@ Opt-out Tag already exists Disable notification light + Interrupt Doze mode for notifications + Android will significantly delay notifications while device is in Doze mode + Android will allow limited interruptions while device is in Doze mode diff --git a/src/main/res/xml/preferences_reminders.xml b/src/main/res/xml/preferences_reminders.xml index d7bfde05c..8b9e01cc1 100644 --- a/src/main/res/xml/preferences_reminders.xml +++ b/src/main/res/xml/preferences_reminders.xml @@ -44,6 +44,13 @@ android:key="@string/p_rmd_persistent" android:summary="@string/persistent_notifications_description" android:title="@string/persistent_notifications" /> +