diff --git a/app/src/googleplay/java/org/tasks/location/GeofenceTransitionsIntentService.kt b/app/src/googleplay/java/org/tasks/location/GeofenceTransitionsIntentService.kt index 11fe0a594..1596cbf25 100644 --- a/app/src/googleplay/java/org/tasks/location/GeofenceTransitionsIntentService.kt +++ b/app/src/googleplay/java/org/tasks/location/GeofenceTransitionsIntentService.kt @@ -9,7 +9,7 @@ import com.todoroo.andlib.utility.DateUtilities import com.todoroo.astrid.reminders.ReminderService import dagger.hilt.android.AndroidEntryPoint import org.tasks.Notifier -import org.tasks.data.LocationDaoBlocking +import org.tasks.data.LocationDao import org.tasks.data.Place import org.tasks.injection.InjectingJobIntentService import org.tasks.notifications.Notification @@ -19,10 +19,10 @@ import javax.inject.Inject @AndroidEntryPoint class GeofenceTransitionsIntentService : InjectingJobIntentService() { - @Inject lateinit var locationDao: LocationDaoBlocking + @Inject lateinit var locationDao: LocationDao @Inject lateinit var notifier: Notifier - override fun doWork(intent: Intent) { + override suspend fun doWork(intent: Intent) { val geofencingEvent = GeofencingEvent.fromIntent(intent) if (geofencingEvent.hasError()) { Timber.e("geofence error code %s", geofencingEvent.errorCode) @@ -40,7 +40,7 @@ class GeofenceTransitionsIntentService : InjectingJobIntentService() { } } - private fun triggerNotification(triggeringGeofence: Geofence, arrival: Boolean) { + private suspend fun triggerNotification(triggeringGeofence: Geofence, arrival: Boolean) { val requestId = triggeringGeofence.requestId try { val place = locationDao.getPlace(requestId) diff --git a/app/src/main/java/org/tasks/data/LocationDaoBlocking.kt b/app/src/main/java/org/tasks/data/LocationDaoBlocking.kt index ad8d38fcf..5ca8ea166 100644 --- a/app/src/main/java/org/tasks/data/LocationDaoBlocking.kt +++ b/app/src/main/java/org/tasks/data/LocationDaoBlocking.kt @@ -13,14 +13,6 @@ class LocationDaoBlocking @Inject constructor(private val dao: LocationDao) { dao.getGeofencesByPlace(uid) } - fun getArrivalGeofences(place: String, now: Long): List = runBlocking { - dao.getArrivalGeofences(place, now) - } - - fun getDepartureGeofences(place: String, now: Long): List = runBlocking { - dao.getDepartureGeofences(place, now) - } - fun getPlaceForTask(taskId: Long): Place? = runBlocking { dao.getPlaceForTask(taskId) } diff --git a/app/src/main/java/org/tasks/injection/InjectingJobIntentService.kt b/app/src/main/java/org/tasks/injection/InjectingJobIntentService.kt index ee8c325fc..4e5293c3f 100644 --- a/app/src/main/java/org/tasks/injection/InjectingJobIntentService.kt +++ b/app/src/main/java/org/tasks/injection/InjectingJobIntentService.kt @@ -2,18 +2,21 @@ package org.tasks.injection import android.content.Intent import androidx.core.app.JobIntentService +import kotlinx.coroutines.runBlocking import timber.log.Timber abstract class InjectingJobIntentService : JobIntentService() { override fun onHandleWork(intent: Intent) { - try { - doWork(intent) - } catch (e: Exception) { - Timber.e(e) + runBlocking { + try { + doWork(intent) + } catch (e: Exception) { + Timber.e(e) + } } } - protected abstract fun doWork(intent: Intent) + protected abstract suspend fun doWork(intent: Intent) companion object { const val JOB_ID_GEOFENCE_TRANSITION = 1081 diff --git a/app/src/main/java/org/tasks/locale/receiver/TaskerIntentService.java b/app/src/main/java/org/tasks/locale/receiver/TaskerIntentService.java deleted file mode 100644 index 95fa47f97..000000000 --- a/app/src/main/java/org/tasks/locale/receiver/TaskerIntentService.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.tasks.locale.receiver; - -import android.content.Intent; -import android.os.Bundle; -import androidx.annotation.NonNull; -import com.todoroo.astrid.api.Filter; -import dagger.hilt.android.AndroidEntryPoint; -import javax.inject.Inject; -import org.tasks.Notifier; -import org.tasks.injection.InjectingJobIntentService; -import org.tasks.locale.bundle.ListNotificationBundle; -import org.tasks.locale.bundle.TaskCreationBundle; -import org.tasks.preferences.DefaultFilterProvider; -import timber.log.Timber; - -@AndroidEntryPoint -public class TaskerIntentService extends InjectingJobIntentService { - - @Inject Notifier notifier; - @Inject DefaultFilterProvider defaultFilterProvider; - @Inject TaskerTaskCreator taskerTaskCreator; - - @Override - protected void doWork(@NonNull Intent intent) { - final Bundle bundle = intent.getBundleExtra(com.twofortyfouram.locale.api.Intent.EXTRA_BUNDLE); - - if (null == bundle) { - Timber.e("%s is missing", com.twofortyfouram.locale.api.Intent.EXTRA_BUNDLE); // $NON-NLS-1$ - return; - } - - if (ListNotificationBundle.isBundleValid(bundle)) { - Filter filter = - defaultFilterProvider.getFilterFromPreferenceBlocking( - bundle.getString(ListNotificationBundle.BUNDLE_EXTRA_STRING_FILTER)); - notifier.triggerFilterNotification(filter); - } else if (TaskCreationBundle.isBundleValid(bundle)) { - taskerTaskCreator.handle(new TaskCreationBundle(bundle)); - } else { - Timber.e("Invalid bundle: %s", bundle); - } - } -} diff --git a/app/src/main/java/org/tasks/locale/receiver/TaskerIntentService.kt b/app/src/main/java/org/tasks/locale/receiver/TaskerIntentService.kt new file mode 100644 index 000000000..eb18d6588 --- /dev/null +++ b/app/src/main/java/org/tasks/locale/receiver/TaskerIntentService.kt @@ -0,0 +1,32 @@ +package org.tasks.locale.receiver + +import android.content.Intent +import dagger.hilt.android.AndroidEntryPoint +import org.tasks.Notifier +import org.tasks.injection.InjectingJobIntentService +import org.tasks.locale.bundle.ListNotificationBundle +import org.tasks.locale.bundle.TaskCreationBundle +import org.tasks.preferences.DefaultFilterProvider +import timber.log.Timber +import javax.inject.Inject + +@AndroidEntryPoint +class TaskerIntentService : InjectingJobIntentService() { + @Inject lateinit var notifier: Notifier + @Inject lateinit var defaultFilterProvider: DefaultFilterProvider + @Inject lateinit var taskerTaskCreator: TaskerTaskCreator + + override suspend fun doWork(intent: Intent) { + val bundle = intent.getBundleExtra(com.twofortyfouram.locale.api.Intent.EXTRA_BUNDLE) + when { + bundle == null -> + Timber.e("${com.twofortyfouram.locale.api.Intent.EXTRA_BUNDLE} is missing") + ListNotificationBundle.isBundleValid(bundle) -> + notifier.triggerFilterNotification(defaultFilterProvider.getFilterFromPreference( + bundle.getString(ListNotificationBundle.BUNDLE_EXTRA_STRING_FILTER))) + TaskCreationBundle.isBundleValid(bundle) -> + taskerTaskCreator.handle(TaskCreationBundle(bundle)) + else -> Timber.e("Invalid bundle: $bundle") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/locale/receiver/TaskerTaskCreator.java b/app/src/main/java/org/tasks/locale/receiver/TaskerTaskCreator.java index cd8144d70..f1b374b72 100644 --- a/app/src/main/java/org/tasks/locale/receiver/TaskerTaskCreator.java +++ b/app/src/main/java/org/tasks/locale/receiver/TaskerTaskCreator.java @@ -15,7 +15,7 @@ import java.time.LocalTime; import java.time.format.DateTimeFormatter; import timber.log.Timber; -class TaskerTaskCreator { +public class TaskerTaskCreator { private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ISO_LOCAL_DATE; private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_LOCAL_TIME; diff --git a/app/src/main/java/org/tasks/preferences/DefaultFilterProvider.kt b/app/src/main/java/org/tasks/preferences/DefaultFilterProvider.kt index 5b377bb21..0f194b52f 100644 --- a/app/src/main/java/org/tasks/preferences/DefaultFilterProvider.kt +++ b/app/src/main/java/org/tasks/preferences/DefaultFilterProvider.kt @@ -28,10 +28,6 @@ class DefaultFilterProvider @Inject constructor( @Deprecated("use coroutines") get() = runBlocking { getFilterFromPreference(R.string.p_dashclock_filter) } set(filter) = setFilterPreference(filter, R.string.p_dashclock_filter) - var badgeFilter: Filter - @Deprecated("use coroutines") get() = runBlocking { getBadgeFilter() } - set(filter) = setFilterPreference(filter, R.string.p_badge_list) - var lastViewedFilter: Filter @Deprecated("use coroutines") get() = runBlocking { getFilterFromPreference(R.string.p_last_viewed_list) } set(filter) = setFilterPreference(filter, R.string.p_last_viewed_list) @@ -44,6 +40,8 @@ class DefaultFilterProvider @Inject constructor( val startupFilter: Filter get() = runBlocking { getStartupFilter() } + fun setBadgeFilter(filter: Filter) = setFilterPreference(filter, R.string.p_badge_list) + suspend fun getBadgeFilter() = getFilterFromPreference(R.string.p_badge_list) suspend fun getDefaultList() = diff --git a/app/src/main/java/org/tasks/preferences/fragments/Notifications.kt b/app/src/main/java/org/tasks/preferences/fragments/Notifications.kt index 30e9aa34a..6576bcd03 100644 --- a/app/src/main/java/org/tasks/preferences/fragments/Notifications.kt +++ b/app/src/main/java/org/tasks/preferences/fragments/Notifications.kt @@ -283,7 +283,7 @@ class Notifications : InjectingPreferenceFragment() { if (resultCode == RESULT_OK) { val filter: Filter = data!!.getParcelableExtra(FilterSelectionActivity.EXTRA_FILTER)!! - defaultFilterProvider.badgeFilter = filter + defaultFilterProvider.setBadgeFilter(filter) findPreference(R.string.p_badge_list).summary = filter.listingTitle localBroadcastManager.broadcastRefresh() } diff --git a/app/src/main/java/org/tasks/receivers/RefreshReceiver.java b/app/src/main/java/org/tasks/receivers/RefreshReceiver.java deleted file mode 100644 index e378b0798..000000000 --- a/app/src/main/java/org/tasks/receivers/RefreshReceiver.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.tasks.receivers; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import androidx.annotation.NonNull; -import com.todoroo.astrid.api.Filter; -import com.todoroo.astrid.dao.TaskDaoBlocking; -import com.todoroo.astrid.provider.Astrid2TaskProvider; -import dagger.hilt.android.AndroidEntryPoint; -import dagger.hilt.android.qualifiers.ApplicationContext; -import javax.inject.Inject; -import org.tasks.R; -import org.tasks.injection.InjectingJobIntentService; -import org.tasks.preferences.DefaultFilterProvider; -import org.tasks.preferences.Preferences; -import org.tasks.provider.TasksContentProvider; -import timber.log.Timber; - -@AndroidEntryPoint -public class RefreshReceiver extends InjectingJobIntentService { - - @Inject @ApplicationContext Context context; - @Inject DefaultFilterProvider defaultFilterProvider; - @Inject TaskDaoBlocking taskDao; - @Inject Preferences preferences; - - @Override - protected void doWork(@NonNull Intent intent) { - if (preferences.getBoolean(R.string.p_badges_enabled, true)) { - Filter badgeFilter = defaultFilterProvider.getBadgeFilter(); - ShortcutBadger.applyCount(context, taskDao.count(badgeFilter)); - } - - try { - ContentResolver cr = context.getContentResolver(); - cr.notifyChange(TasksContentProvider.CONTENT_URI, null); - cr.notifyChange(Astrid2TaskProvider.CONTENT_URI, null); - } catch (Exception e) { - Timber.e(e); - } - } -} diff --git a/app/src/main/java/org/tasks/receivers/RefreshReceiver.kt b/app/src/main/java/org/tasks/receivers/RefreshReceiver.kt new file mode 100644 index 000000000..91156cfc8 --- /dev/null +++ b/app/src/main/java/org/tasks/receivers/RefreshReceiver.kt @@ -0,0 +1,37 @@ +package org.tasks.receivers + +import android.content.Context +import android.content.Intent +import com.todoroo.astrid.dao.TaskDao +import com.todoroo.astrid.provider.Astrid2TaskProvider +import dagger.hilt.android.AndroidEntryPoint +import dagger.hilt.android.qualifiers.ApplicationContext +import org.tasks.R +import org.tasks.injection.InjectingJobIntentService +import org.tasks.preferences.DefaultFilterProvider +import org.tasks.preferences.Preferences +import org.tasks.provider.TasksContentProvider +import timber.log.Timber +import javax.inject.Inject + +@AndroidEntryPoint +class RefreshReceiver : InjectingJobIntentService() { + @Inject @ApplicationContext lateinit var context: Context + @Inject lateinit var defaultFilterProvider: DefaultFilterProvider + @Inject lateinit var taskDao: TaskDao + @Inject lateinit var preferences: Preferences + + override suspend fun doWork(intent: Intent) { + if (preferences.getBoolean(R.string.p_badges_enabled, true)) { + val badgeFilter = defaultFilterProvider.getBadgeFilter() + ShortcutBadger.applyCount(context, taskDao.count(badgeFilter)) + } + try { + val cr = context.contentResolver + cr.notifyChange(TasksContentProvider.CONTENT_URI, null) + cr.notifyChange(Astrid2TaskProvider.CONTENT_URI, null) + } catch (e: Exception) { + Timber.e(e) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/scheduling/CalendarNotificationIntentService.java b/app/src/main/java/org/tasks/scheduling/CalendarNotificationIntentService.java deleted file mode 100644 index cf4c9944f..000000000 --- a/app/src/main/java/org/tasks/scheduling/CalendarNotificationIntentService.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.tasks.scheduling; - -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import androidx.core.app.JobIntentService; -import com.todoroo.andlib.utility.DateUtilities; -import com.todoroo.astrid.gcal.CalendarAlarmReceiver; -import dagger.hilt.android.AndroidEntryPoint; -import dagger.hilt.android.qualifiers.ApplicationContext; -import java.util.concurrent.TimeUnit; -import javax.inject.Inject; -import org.tasks.R; -import org.tasks.calendars.AndroidCalendarEvent; -import org.tasks.calendars.CalendarEventProvider; -import org.tasks.injection.InjectingJobIntentService; -import org.tasks.preferences.Preferences; -import timber.log.Timber; - -@AndroidEntryPoint -public class CalendarNotificationIntentService extends RecurringIntervalIntentService { - - public static final String URI_PREFIX_POSTPONE = "cal-postpone"; - private static final long FIFTEEN_MINUTES = TimeUnit.MINUTES.toMillis(15); - private static final String URI_PREFIX = "cal-reminder"; - @Inject Preferences preferences; - @Inject CalendarEventProvider calendarEventProvider; - @Inject @ApplicationContext Context context; - @Inject AlarmManager alarmManager; - - public static void enqueueWork(Context context) { - JobIntentService.enqueueWork( - context, - CalendarNotificationIntentService.class, - InjectingJobIntentService.JOB_ID_CALENDAR_NOTIFICATION, - new Intent(context, CalendarNotificationIntentService.class)); - } - - @Override - Class getBroadcastClass() { - return Broadcast.class; - } - - @Override - void run() { - long now = DateUtilities.now(); - long end = now + TimeUnit.DAYS.toMillis(1); - - for (final AndroidCalendarEvent event : calendarEventProvider.getEventsBetween(now, end)) { - Intent eventAlarm = new Intent(context, CalendarAlarmReceiver.class); - eventAlarm.setAction(CalendarAlarmReceiver.BROADCAST_CALENDAR_REMINDER); - eventAlarm.setData(Uri.parse(URI_PREFIX + "://" + event.getId())); - - PendingIntent pendingIntent = - PendingIntent.getBroadcast( - context, - CalendarAlarmReceiver.REQUEST_CODE_CAL_REMINDER, - eventAlarm, - PendingIntent.FLAG_UPDATE_CURRENT); - - long reminderTime = event.getStart() - FIFTEEN_MINUTES; - alarmManager.wakeup(reminderTime, pendingIntent); - Timber.d("Scheduled reminder for %s at %s", event, reminderTime); - } - } - - @Override - long intervalMillis() { - return preferences.getBoolean(R.string.p_calendar_reminders, false) - ? TimeUnit.HOURS.toMillis(12) - : 0; - } - - public static class Broadcast extends BroadcastReceiver { - - @Override - public void onReceive(Context context, Intent intent) { - enqueueWork(context); - } - } -} diff --git a/app/src/main/java/org/tasks/scheduling/CalendarNotificationIntentService.kt b/app/src/main/java/org/tasks/scheduling/CalendarNotificationIntentService.kt new file mode 100644 index 000000000..a138854a2 --- /dev/null +++ b/app/src/main/java/org/tasks/scheduling/CalendarNotificationIntentService.kt @@ -0,0 +1,70 @@ +package org.tasks.scheduling + +import android.app.PendingIntent +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.net.Uri +import com.todoroo.andlib.utility.DateUtilities +import com.todoroo.astrid.gcal.CalendarAlarmReceiver +import dagger.hilt.android.AndroidEntryPoint +import dagger.hilt.android.qualifiers.ApplicationContext +import org.tasks.R +import org.tasks.calendars.CalendarEventProvider +import org.tasks.preferences.Preferences +import timber.log.Timber +import java.util.concurrent.TimeUnit +import javax.inject.Inject + +@AndroidEntryPoint +class CalendarNotificationIntentService : RecurringIntervalIntentService() { + @Inject lateinit var preferences: Preferences + @Inject lateinit var calendarEventProvider: CalendarEventProvider + @Inject @ApplicationContext lateinit var context: Context + + override val broadcastClass = Broadcast::class.java + + override suspend fun run() { + val now = DateUtilities.now() + val end = now + TimeUnit.DAYS.toMillis(1) + for (event in calendarEventProvider.getEventsBetween(now, end)) { + val eventAlarm = Intent(context, CalendarAlarmReceiver::class.java) + eventAlarm.action = CalendarAlarmReceiver.BROADCAST_CALENDAR_REMINDER + eventAlarm.data = Uri.parse(URI_PREFIX + "://" + event.id) + val pendingIntent = PendingIntent.getBroadcast( + context, + CalendarAlarmReceiver.REQUEST_CODE_CAL_REMINDER, + eventAlarm, + PendingIntent.FLAG_UPDATE_CURRENT) + val reminderTime = event.start - FIFTEEN_MINUTES + alarmManager.wakeup(reminderTime, pendingIntent) + Timber.d("Scheduled reminder for %s at %s", event, reminderTime) + } + } + + override fun intervalMillis() = + if (preferences.getBoolean(R.string.p_calendar_reminders, false)) { + TimeUnit.HOURS.toMillis(12) + } else { + 0 + } + + class Broadcast : BroadcastReceiver() { + override fun onReceive(context: Context, intent: Intent) { + enqueueWork(context) + } + } + + companion object { + const val URI_PREFIX_POSTPONE = "cal-postpone" + private val FIFTEEN_MINUTES = TimeUnit.MINUTES.toMillis(15) + private const val URI_PREFIX = "cal-reminder" + fun enqueueWork(context: Context?) { + enqueueWork( + context!!, + CalendarNotificationIntentService::class.java, + JOB_ID_CALENDAR_NOTIFICATION, + Intent(context, CalendarNotificationIntentService::class.java)) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/scheduling/NotificationSchedulerIntentService.java b/app/src/main/java/org/tasks/scheduling/NotificationSchedulerIntentService.java deleted file mode 100644 index f679fb1b9..000000000 --- a/app/src/main/java/org/tasks/scheduling/NotificationSchedulerIntentService.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.tasks.scheduling; - -import static com.todoroo.andlib.utility.AndroidUtilities.atLeastOreo; -import static org.tasks.notifications.NotificationManager.NOTIFICATION_CHANNEL_DEFAULT; -import static org.tasks.notifications.NotificationManager.NOTIFICATION_CHANNEL_MISCELLANEOUS; -import static org.tasks.notifications.NotificationManager.NOTIFICATION_CHANNEL_TASKER; -import static org.tasks.notifications.NotificationManager.NOTIFICATION_CHANNEL_TIMERS; - -import android.annotation.TargetApi; -import android.app.NotificationChannel; -import android.content.Context; -import android.content.Intent; -import android.os.Build; -import androidx.core.app.JobIntentService; -import com.todoroo.astrid.alarms.AlarmService; -import com.todoroo.astrid.reminders.ReminderService; -import dagger.hilt.android.AndroidEntryPoint; -import dagger.hilt.android.qualifiers.ApplicationContext; -import javax.inject.Inject; -import org.tasks.R; -import org.tasks.injection.InjectingJobIntentService; -import org.tasks.jobs.NotificationQueue; -import org.tasks.notifications.NotificationManager; -import timber.log.Timber; - -@AndroidEntryPoint -public class NotificationSchedulerIntentService extends InjectingJobIntentService { - - private static final String EXTRA_CANCEL_EXISTING_NOTIFICATIONS = - "extra_cancel_existing_notifications"; - @Inject @ApplicationContext Context context; - @Inject AlarmService alarmService; - @Inject ReminderService reminderService; - @Inject NotificationQueue notificationQueue; - @Inject NotificationManager notificationManager; - - public static void enqueueWork(Context context, boolean cancelNotifications) { - Intent intent = new Intent(context, NotificationSchedulerIntentService.class); - intent.putExtra(EXTRA_CANCEL_EXISTING_NOTIFICATIONS, cancelNotifications); - JobIntentService.enqueueWork( - context, - NotificationSchedulerIntentService.class, - InjectingJobIntentService.JOB_ID_NOTIFICATION_SCHEDULER, - intent); - } - - @Override - protected void doWork(Intent intent) { - Timber.d("onHandleWork(%s)", intent); - - createNotificationChannels(); - - notificationQueue.clear(); - - boolean cancelExistingNotifications = - intent.getBooleanExtra(EXTRA_CANCEL_EXISTING_NOTIFICATIONS, false); - - notificationManager.restoreNotifications(cancelExistingNotifications); - reminderService.scheduleAllAlarms(); - alarmService.scheduleAllAlarms(); - } - - private void createNotificationChannels() { - if (atLeastOreo()) { - android.app.NotificationManager notificationManager = - (android.app.NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.createNotificationChannel( - createNotificationChannel(NOTIFICATION_CHANNEL_DEFAULT, R.string.notifications, true)); - notificationManager.createNotificationChannel( - createNotificationChannel(NOTIFICATION_CHANNEL_TASKER, R.string.tasker_locale, true)); - notificationManager.createNotificationChannel( - createNotificationChannel( - NOTIFICATION_CHANNEL_TIMERS, R.string.TEA_timer_controls, true)); - notificationManager.createNotificationChannel( - createNotificationChannel( - NOTIFICATION_CHANNEL_MISCELLANEOUS, R.string.miscellaneous, false)); - } - } - - @TargetApi(Build.VERSION_CODES.O) - private NotificationChannel createNotificationChannel( - String channelId, int nameResId, boolean alert) { - String channelName = context.getString(nameResId); - int importance = - alert - ? android.app.NotificationManager.IMPORTANCE_HIGH - : android.app.NotificationManager.IMPORTANCE_LOW; - NotificationChannel notificationChannel = - new NotificationChannel(channelId, channelName, importance); - notificationChannel.enableLights(alert); - notificationChannel.enableVibration(alert); - notificationChannel.setBypassDnd(alert); - notificationChannel.setShowBadge(alert); - return notificationChannel; - } -} diff --git a/app/src/main/java/org/tasks/scheduling/NotificationSchedulerIntentService.kt b/app/src/main/java/org/tasks/scheduling/NotificationSchedulerIntentService.kt new file mode 100644 index 000000000..1c20985ef --- /dev/null +++ b/app/src/main/java/org/tasks/scheduling/NotificationSchedulerIntentService.kt @@ -0,0 +1,79 @@ +package org.tasks.scheduling + +import android.annotation.TargetApi +import android.app.NotificationChannel +import android.content.Context +import android.content.Intent +import android.os.Build +import com.todoroo.andlib.utility.AndroidUtilities +import com.todoroo.astrid.alarms.AlarmService +import com.todoroo.astrid.reminders.ReminderService +import dagger.hilt.android.AndroidEntryPoint +import dagger.hilt.android.qualifiers.ApplicationContext +import org.tasks.R +import org.tasks.injection.InjectingJobIntentService +import org.tasks.jobs.NotificationQueue +import org.tasks.notifications.NotificationManager +import timber.log.Timber +import javax.inject.Inject + +@AndroidEntryPoint +class NotificationSchedulerIntentService : InjectingJobIntentService() { + @Inject @ApplicationContext lateinit var context: Context + @Inject lateinit var alarmService: AlarmService + @Inject lateinit var reminderService: ReminderService + @Inject lateinit var notificationQueue: NotificationQueue + @Inject lateinit var notificationManager: NotificationManager + + override suspend fun doWork(intent: Intent) { + Timber.d("onHandleWork(%s)", intent) + createNotificationChannels() + notificationQueue.clear() + val cancelExistingNotifications = intent.getBooleanExtra(EXTRA_CANCEL_EXISTING_NOTIFICATIONS, false) + notificationManager.restoreNotifications(cancelExistingNotifications) + reminderService.scheduleAllAlarms() + alarmService.scheduleAllAlarms() + } + + private fun createNotificationChannels() { + if (AndroidUtilities.atLeastOreo()) { + val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as android.app.NotificationManager + notificationManager.createNotificationChannel( + createNotificationChannel(NotificationManager.NOTIFICATION_CHANNEL_DEFAULT, R.string.notifications, true)) + notificationManager.createNotificationChannel( + createNotificationChannel(NotificationManager.NOTIFICATION_CHANNEL_TASKER, R.string.tasker_locale, true)) + notificationManager.createNotificationChannel( + createNotificationChannel( + NotificationManager.NOTIFICATION_CHANNEL_TIMERS, R.string.TEA_timer_controls, true)) + notificationManager.createNotificationChannel( + createNotificationChannel( + NotificationManager.NOTIFICATION_CHANNEL_MISCELLANEOUS, R.string.miscellaneous, false)) + } + } + + @TargetApi(Build.VERSION_CODES.O) + private fun createNotificationChannel( + channelId: String, nameResId: Int, alert: Boolean): NotificationChannel { + val channelName = context.getString(nameResId) + val importance = if (alert) android.app.NotificationManager.IMPORTANCE_HIGH else android.app.NotificationManager.IMPORTANCE_LOW + val notificationChannel = NotificationChannel(channelId, channelName, importance) + notificationChannel.enableLights(alert) + notificationChannel.enableVibration(alert) + notificationChannel.setBypassDnd(alert) + notificationChannel.setShowBadge(alert) + return notificationChannel + } + + companion object { + private const val EXTRA_CANCEL_EXISTING_NOTIFICATIONS = "extra_cancel_existing_notifications" + fun enqueueWork(context: Context?, cancelNotifications: Boolean) { + val intent = Intent(context, NotificationSchedulerIntentService::class.java) + intent.putExtra(EXTRA_CANCEL_EXISTING_NOTIFICATIONS, cancelNotifications) + enqueueWork( + context!!, + NotificationSchedulerIntentService::class.java, + JOB_ID_NOTIFICATION_SCHEDULER, + intent) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.java b/app/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.java deleted file mode 100644 index 91150d356..000000000 --- a/app/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.tasks.scheduling; - -import static org.tasks.time.DateTimeUtils.currentTimeMillis; -import static org.tasks.time.DateTimeUtils.printTimestamp; - -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Intent; -import javax.inject.Inject; -import org.tasks.injection.InjectingJobIntentService; -import timber.log.Timber; - -public abstract class RecurringIntervalIntentService extends InjectingJobIntentService { - - @Inject AlarmManager alarmManager; - - @Override - protected void doWork(Intent intent) { - long interval = intervalMillis(); - - if (interval <= 0) { - Timber.d("service disabled"); - return; - } - - long now = currentTimeMillis(); - long nextRun = now + interval; - Timber.d("running now [nextRun=%s]", printTimestamp(nextRun)); - run(); - - PendingIntent pendingIntent = - PendingIntent.getBroadcast( - this, 0, new Intent(this, getBroadcastClass()), PendingIntent.FLAG_UPDATE_CURRENT); - alarmManager.wakeup(nextRun, pendingIntent); - } - - abstract Class getBroadcastClass(); - - abstract void run(); - - abstract long intervalMillis(); -} diff --git a/app/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.kt b/app/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.kt new file mode 100644 index 000000000..c3b32ed35 --- /dev/null +++ b/app/src/main/java/org/tasks/scheduling/RecurringIntervalIntentService.kt @@ -0,0 +1,32 @@ +package org.tasks.scheduling + +import android.app.PendingIntent +import android.content.BroadcastReceiver +import android.content.Intent +import org.tasks.injection.InjectingJobIntentService +import org.tasks.time.DateTimeUtils +import timber.log.Timber +import javax.inject.Inject + +abstract class RecurringIntervalIntentService : InjectingJobIntentService() { + @Inject lateinit var alarmManager: AlarmManager + + override suspend fun doWork(intent: Intent) { + val interval = intervalMillis() + if (interval <= 0) { + Timber.d("service disabled") + return + } + val now = DateTimeUtils.currentTimeMillis() + val nextRun = now + interval + Timber.d("running now [nextRun=${DateTimeUtils.printTimestamp(nextRun)}]") + run() + val pendingIntent = PendingIntent.getBroadcast( + this, 0, Intent(this, broadcastClass), PendingIntent.FLAG_UPDATE_CURRENT) + alarmManager.wakeup(nextRun, pendingIntent) + } + + abstract val broadcastClass: Class + abstract suspend fun run() + abstract fun intervalMillis(): Long +} \ No newline at end of file