15
15
import static com .mindful .android .receivers .alarm .BedtimeRoutineReceiver .ACTION_ALERT_BEDTIME ;
16
16
import static com .mindful .android .receivers .alarm .BedtimeRoutineReceiver .ACTION_START_BEDTIME ;
17
17
import static com .mindful .android .receivers .alarm .BedtimeRoutineReceiver .ACTION_STOP_BEDTIME ;
18
+ import static com .mindful .android .receivers .alarm .NotificationBatchReceiver .ACTION_PUSH_BATCH ;
19
+ import static com .mindful .android .utils .AppConstants .ONE_DAY_IN_MS ;
18
20
19
21
import android .app .AlarmManager ;
20
22
import android .app .PendingIntent ;
21
23
import android .content .Context ;
22
24
import android .content .Intent ;
23
25
import android .os .Build ;
24
- import android .os .Handler ;
25
26
import android .util .Log ;
26
27
27
28
import androidx .annotation .NonNull ;
30
31
import com .mindful .android .models .BedtimeSettings ;
31
32
import com .mindful .android .receivers .alarm .BedtimeRoutineReceiver ;
32
33
import com .mindful .android .receivers .alarm .MidnightResetReceiver ;
34
+ import com .mindful .android .receivers .alarm .NotificationBatchReceiver ;
33
35
import com .mindful .android .services .MindfulTrackerService ;
34
36
import com .mindful .android .utils .Utils ;
35
37
38
+ import java .util .Arrays ;
36
39
import java .util .Calendar ;
40
+ import java .util .Collections ;
37
41
import java .util .Date ;
42
+ import java .util .HashSet ;
43
+ import java .util .List ;
44
+ import java .util .stream .Collectors ;
38
45
39
46
/**
40
47
* Helper class for scheduling alarm tasks related to bedtime routines and midnight resets.
41
48
*/
42
49
public class AlarmTasksSchedulingHelper {
43
50
private static final String TAG = "Mindful.AlarmTasksSchedulingHelper" ;
44
- private static final long oneDayInMs = 24 * 60 * 60 * 1000 ;
45
51
46
52
/**
47
53
* Schedules the midnight reset task if it is not already scheduled.
@@ -67,7 +73,7 @@ public static void scheduleMidnightResetTask(@NonNull Context context, boolean c
67
73
cal .set (Calendar .SECOND , 3 ); // For safe side
68
74
cal .add (Calendar .DATE , 1 );
69
75
70
- scheduleOrUpdateAlarmTask (context , MidnightResetReceiver .class , MidnightResetReceiver .ACTION_START_MIDNIGHT_RESET , cal .getTimeInMillis ());
76
+ scheduleOrUpdateExactAlarmTask (context , MidnightResetReceiver .class , MidnightResetReceiver .ACTION_START_MIDNIGHT_RESET , cal .getTimeInMillis ());
71
77
Log .d (TAG , "scheduleMidnightTask: Midnight reset task scheduled successfully for " + cal .getTime ());
72
78
}
73
79
@@ -85,19 +91,19 @@ public static void scheduleBedtimeRoutineTasks(@NonNull Context context, @NonNul
85
91
86
92
// Bedtime is already ended then reschedule for the next day
87
93
if (endTimeMs < nowInMs ) {
88
- alertTimeMs += oneDayInMs ;
89
- startTimeMs += oneDayInMs ;
90
- endTimeMs += oneDayInMs ;
94
+ alertTimeMs += ONE_DAY_IN_MS ;
95
+ startTimeMs += ONE_DAY_IN_MS ;
96
+ endTimeMs += ONE_DAY_IN_MS ;
91
97
}
92
98
93
99
// If alert time is in future
94
100
if (alertTimeMs > nowInMs ) {
95
- scheduleOrUpdateAlarmTask (context , BedtimeRoutineReceiver .class , ACTION_ALERT_BEDTIME , alertTimeMs );
101
+ scheduleOrUpdateExactAlarmTask (context , BedtimeRoutineReceiver .class , ACTION_ALERT_BEDTIME , alertTimeMs );
96
102
}
97
103
98
104
// Bedtime start and stop tasks
99
- scheduleOrUpdateAlarmTask (context , BedtimeRoutineReceiver .class , ACTION_START_BEDTIME , startTimeMs );
100
- scheduleOrUpdateAlarmTask (context , BedtimeRoutineReceiver .class , ACTION_STOP_BEDTIME , endTimeMs );
105
+ scheduleOrUpdateExactAlarmTask (context , BedtimeRoutineReceiver .class , ACTION_START_BEDTIME , startTimeMs );
106
+ scheduleOrUpdateExactAlarmTask (context , BedtimeRoutineReceiver .class , ACTION_STOP_BEDTIME , endTimeMs );
101
107
Log .d (TAG , "scheduleBedtimeStartTask: Bedtime routine tasks scheduled successfully for - "
102
108
+ "\n alert: " + (alertTimeMs > nowInMs ? "" : "(skipping) " ) + new Date (alertTimeMs )
103
109
+ "\n start: " + new Date (startTimeMs )
@@ -112,18 +118,8 @@ public static void scheduleBedtimeRoutineTasks(@NonNull Context context, @NonNul
112
118
* @param context The application context.
113
119
*/
114
120
public static void cancelBedtimeRoutineTasks (@ NonNull Context context ) {
115
- Intent alertIntent = new Intent (context .getApplicationContext (), BedtimeRoutineReceiver .class ).setAction (ACTION_ALERT_BEDTIME );
116
- Intent startIntent = new Intent (context .getApplicationContext (), BedtimeRoutineReceiver .class ).setAction (ACTION_START_BEDTIME );
117
- Intent stopIntent = new Intent (context .getApplicationContext (), BedtimeRoutineReceiver .class ).setAction (BedtimeRoutineReceiver .ACTION_STOP_BEDTIME );
118
- PendingIntent alertPendingIntent = PendingIntent .getBroadcast (context , 0 , alertIntent , PendingIntent .FLAG_UPDATE_CURRENT | PendingIntent .FLAG_IMMUTABLE );
119
- PendingIntent startPendingIntent = PendingIntent .getBroadcast (context , 0 , startIntent , PendingIntent .FLAG_UPDATE_CURRENT | PendingIntent .FLAG_IMMUTABLE );
120
- PendingIntent stopPendingIntent = PendingIntent .getBroadcast (context , 0 , stopIntent , PendingIntent .FLAG_UPDATE_CURRENT | PendingIntent .FLAG_IMMUTABLE );
121
-
122
121
// Cancel the alarms
123
- AlarmManager alarmManager = (AlarmManager ) context .getSystemService (Context .ALARM_SERVICE );
124
- alarmManager .cancel (alertPendingIntent );
125
- alarmManager .cancel (startPendingIntent );
126
- alarmManager .cancel (stopPendingIntent );
122
+ cancelExactAlarmTasks (context , BedtimeRoutineReceiver .class , Arrays .asList (ACTION_ALERT_BEDTIME , ACTION_START_BEDTIME , ACTION_STOP_BEDTIME ));
127
123
128
124
// Let service know
129
125
if (Utils .isServiceRunning (context , MindfulTrackerService .class .getName ())) {
@@ -135,6 +131,47 @@ public static void cancelBedtimeRoutineTasks(@NonNull Context context) {
135
131
Log .d (TAG , "cancelBedtimeRoutineTasks: Bedtime routine tasks cancelled successfully" );
136
132
}
137
133
134
+ /**
135
+ * Schedules next future possible notification batch.
136
+ *
137
+ * @param context The application context.
138
+ * @param scheduleTods The hashset of integers representing TODs in minutes.
139
+ */
140
+ public static void scheduleNotificationBatchTask (@ NonNull Context context , @ NonNull HashSet <Integer > scheduleTods ) {
141
+ List <Integer > sortedTods = scheduleTods .stream ().sorted ().collect (Collectors .toList ());
142
+ if (sortedTods .isEmpty ()) return ;
143
+
144
+ long now = System .currentTimeMillis ();
145
+ Long nextAlarmTime = null ;
146
+
147
+ // Find the first future TOD
148
+ for (int tod : sortedTods ) {
149
+ long currentTime = Utils .todToTodayCal (tod ).getTimeInMillis ();
150
+ if (currentTime > now ) {
151
+ nextAlarmTime = currentTime ;
152
+ break ;
153
+ }
154
+ }
155
+
156
+ // If no future TOD, schedule for the first TOD of the next day
157
+ if (nextAlarmTime == null ) {
158
+ nextAlarmTime = Utils .todToTodayCal (sortedTods .get (0 )).getTimeInMillis () + ONE_DAY_IN_MS ;
159
+ }
160
+
161
+ scheduleOrUpdateExactAlarmTask (context , NotificationBatchReceiver .class , ACTION_PUSH_BATCH , nextAlarmTime );
162
+ Log .d (TAG , "scheduleNotificationBatchTask: Notification batch task scheduled successfully for " + new Date (nextAlarmTime ));
163
+ }
164
+
165
+ /**
166
+ * Cancels notification batch schedule task.
167
+ *
168
+ * @param context The application context.
169
+ */
170
+ public static void cancelNotificationBatchTask (@ NonNull Context context ) {
171
+ cancelExactAlarmTasks (context , NotificationBatchReceiver .NotificationBatchWorker .class , Collections .singletonList (ACTION_PUSH_BATCH ));
172
+ Log .d (TAG , "cancelNotificationBatchTask: Notification batch tasks cancelled successfully" );
173
+ }
174
+
138
175
/**
139
176
* Schedules or updates an alarm task with the specified parameters.
140
177
*
@@ -143,7 +180,7 @@ public static void cancelBedtimeRoutineTasks(@NonNull Context context) {
143
180
* @param intentAction The action to be set on the intent.
144
181
* @param epochTimeMs The time at which the alarm should go off, in milliseconds since epoch.
145
182
*/
146
- private static void scheduleOrUpdateAlarmTask (@ NonNull Context context , Class <?> receiverClass , String intentAction , long epochTimeMs ) {
183
+ private static void scheduleOrUpdateExactAlarmTask (@ NonNull Context context , Class <?> receiverClass , String intentAction , long epochTimeMs ) {
147
184
AlarmManager alarmManager = (AlarmManager ) context .getSystemService (Context .ALARM_SERVICE );
148
185
Intent intent = new Intent (context .getApplicationContext (), receiverClass ).setAction (intentAction );
149
186
PendingIntent pendingIntent = PendingIntent .getBroadcast (context , 0 , intent , PendingIntent .FLAG_UPDATE_CURRENT | PendingIntent .FLAG_IMMUTABLE );
@@ -156,4 +193,23 @@ private static void scheduleOrUpdateAlarmTask(@NonNull Context context, Class<?>
156
193
alarmManager .setExactAndAllowWhileIdle (AlarmManager .RTC_WAKEUP , epochTimeMs , pendingIntent );
157
194
}
158
195
}
196
+
197
+ /**
198
+ * Cancels all the exact alarm task related to the service class and the list of actions.
199
+ *
200
+ * @param context The application context.
201
+ * @param receiverClass The receiver class for the alarm.
202
+ * @param intentActions The list of actions to be set on the intents.
203
+ */
204
+ private static void cancelExactAlarmTasks (@ NonNull Context context , Class <?> receiverClass , @ NonNull List <String > intentActions ) {
205
+ AlarmManager alarmManager = (AlarmManager ) context .getSystemService (Context .ALARM_SERVICE );
206
+
207
+ for (String action : intentActions ) {
208
+ Intent intent = new Intent (context .getApplicationContext (), receiverClass ).setAction (action );
209
+ PendingIntent pendingIntent = PendingIntent .getBroadcast (context , 0 , intent , PendingIntent .FLAG_UPDATE_CURRENT | PendingIntent .FLAG_IMMUTABLE );
210
+ alarmManager .cancel (pendingIntent );
211
+ }
212
+ }
213
+
214
+
159
215
}
0 commit comments