7
7
import org .dmfs .provider .tasks .TaskDatabaseHelper .Tables ;
8
8
import org .dmfs .provider .tasks .TaskProvider ;
9
9
10
+ import android .annotation .TargetApi ;
10
11
import android .app .AlarmManager ;
11
12
import android .app .PendingIntent ;
12
13
import android .content .BroadcastReceiver ;
15
16
import android .database .Cursor ;
16
17
import android .database .sqlite .SQLiteDatabase ;
17
18
import android .database .sqlite .SQLiteOpenHelper ;
19
+ import android .os .Build ;
18
20
19
21
20
22
/**
@@ -64,25 +66,33 @@ public AlarmNotificationHandler(Context context)
64
66
*
65
67
* @param taskId
66
68
* The row id of the task to set an alarm for.
67
- * @param dueDate
69
+ * @param dueTime
68
70
* The date in milliseconds when the task is due.
69
71
* @param taskTitle
70
72
* The title of the task.
71
73
*/
72
- public void setDueAlarm (long taskId , long dueDate , String taskTitle )
74
+ @ TargetApi (19 )
75
+ public void setDueAlarm (long taskId , long dueTime , String taskTitle )
73
76
{
74
77
Context context = mContext .get ();
75
78
if (context != null )
76
79
{
77
80
Intent intentAlarm = new Intent (context , AlarmNotificationHandler .class );
78
81
intentAlarm .putExtra (EXTRA_TASK_ID , taskId );
79
- intentAlarm .putExtra (EXTRA_TASK_DUE_TIME , dueDate );
82
+ intentAlarm .putExtra (EXTRA_TASK_DUE_TIME , dueTime );
80
83
intentAlarm .putExtra (EXTRA_TASK_TITLE , taskTitle );
81
-
82
84
PendingIntent pendingIntent = PendingIntent .getBroadcast (context , REQUEST_CODE_DUE_ALARM , intentAlarm , PendingIntent .FLAG_UPDATE_CURRENT );
83
- mAlarmManager .set (AlarmManager .RTC_WAKEUP , dueDate , pendingIntent );
84
- }
85
85
86
+ // AlarmManager API changed in v19 (KitKat) and the "set" method is not called at the exact time anymore
87
+ if (Build .VERSION .SDK_INT > 18 )
88
+ {
89
+ mAlarmManager .setExact (AlarmManager .RTC_WAKEUP , dueTime , pendingIntent );
90
+ }
91
+ else
92
+ {
93
+ mAlarmManager .set (AlarmManager .RTC_WAKEUP , dueTime , pendingIntent );
94
+ }
95
+ }
86
96
}
87
97
88
98
@@ -91,20 +101,25 @@ public void setDueAlarm(long taskId, long dueDate, String taskTitle)
91
101
*
92
102
* @param db
93
103
* The {@link SQLiteDatabase}.
104
+ * @param time
105
+ * The absolute minimum time in milliseconds when the next alarm can be due.
106
+ *
94
107
*/
95
- public void setUpcomingDueAlarm (SQLiteDatabase db )
108
+ public void setUpcomingDueAlarm (SQLiteDatabase db , long time )
96
109
{
97
110
mDb = db ;
98
111
String [] projection = new String [] { Instances .TASK_ID , Instances .INSTANCE_DUE , Tasks .TITLE };
99
- String selection = System . currentTimeMillis () + " <= " + Instances .INSTANCE_DUE ;
112
+ String selection = time + " <= " + Instances .INSTANCE_DUE ;
100
113
Cursor cursor = db .query (Tables .INSTANCE_VIEW , projection , selection , null , null , null , Instances .INSTANCE_DUE , "1" );
101
114
102
115
if (cursor != null )
103
116
{
104
117
try
105
118
{
106
- cursor .moveToFirst ();
107
- setDueAlarm (cursor .getLong (0 ), cursor .getLong (1 ), cursor .getString (2 ));
119
+ if (cursor .moveToFirst ())
120
+ {
121
+ setDueAlarm (cursor .getLong (0 ), cursor .getLong (1 ), cursor .getString (2 ));
122
+ }
108
123
}
109
124
finally
110
125
{
@@ -120,25 +135,58 @@ public void setUpcomingDueAlarm(SQLiteDatabase db)
120
135
@ Override
121
136
public void onReceive (Context context , Intent intent )
122
137
{
138
+ mContext = new SoftReference <Context >(context );
139
+ mAlarmManager = (AlarmManager ) context .getSystemService (Context .ALARM_SERVICE );
123
140
if (intent .hasExtra (EXTRA_TASK_ID ))
124
141
{
125
- // Alarm went off -> inform the application
126
- mContext = new SoftReference <Context >(context );
127
- sendTaskDueAlarmBroadcast (intent .getLongExtra (EXTRA_TASK_ID , 0 ), intent .getLongExtra (EXTRA_TASK_DUE_TIME , System .currentTimeMillis ()),
128
- intent .getStringExtra (EXTRA_TASK_TITLE ));
129
142
130
- if (mDb != null )
143
+ SQLiteDatabase db ;
144
+ if (mDb == null )
145
+ {
146
+ SQLiteOpenHelper dBHelper = new TaskProvider ().getDatabaseHelper (context );
147
+ db = dBHelper .getReadableDatabase ();
148
+ mDb = db ;
149
+ }
150
+
151
+ // check for all tasks which are due since the due alarm was set plus 1 second
152
+ long currentDueTime = intent .getExtras ().getLong (EXTRA_TASK_DUE_TIME );
153
+ long nextDueTime = currentDueTime + 1000 ;
154
+ String [] projection = new String [] { Instances .TASK_ID , Instances .INSTANCE_DUE , Tasks .TITLE };
155
+ String selection = nextDueTime + " > " + Instances .INSTANCE_DUE + " AND " + currentDueTime + " <= " + Instances .INSTANCE_DUE ;
156
+ Cursor cursor = mDb .query (Tables .INSTANCE_VIEW , projection , selection , null , null , null , Instances .INSTANCE_DUE );
157
+
158
+ if (cursor != null )
131
159
{
132
- setUpcomingDueAlarm (mDb );
160
+ try
161
+ {
162
+ if (cursor .moveToFirst ())
163
+ {
164
+ while (!cursor .isAfterLast ())
165
+ {
166
+ // inform the application
167
+ sendTaskDueAlarmBroadcast (cursor .getLong (0 ), cursor .getLong (1 ), cursor .getString (2 ));
168
+ cursor .moveToNext ();
169
+ }
170
+
171
+ }
172
+ }
173
+ finally
174
+ {
175
+ cursor .close ();
176
+ }
133
177
}
178
+ // Set the next alarm
179
+ setUpcomingDueAlarm (mDb , nextDueTime );
180
+ mDb .close ();
134
181
}
135
182
else if (intent .getAction ().equals ("android.intent.action.BOOT_COMPLETED" ))
136
183
{
137
184
// device booted -> set upcoming alarm
138
185
mContext = new SoftReference <Context >(context );
186
+ mAlarmManager = (AlarmManager ) context .getSystemService (Context .ALARM_SERVICE );
139
187
SQLiteOpenHelper dBHelper = new TaskProvider ().getDatabaseHelper (context );
140
188
SQLiteDatabase db = dBHelper .getReadableDatabase ();
141
- setUpcomingDueAlarm (db );
189
+ setUpcomingDueAlarm (db , System . currentTimeMillis () );
142
190
db .close ();
143
191
144
192
}
0 commit comments