I have only just started to learn Android programming and am currently creating a simple reminder application. Through some intro books, online blogs and of course many a Stack overflow page I have gotten it to a pretty good point. All except being able to reset my alarms when the phone reboots.
I have a BroadcastReceiver class which handles my alarms currently, and have given it the correct permissions in my manifest to handle 'RECEIVE_BOOT_COMPLETED'. However when I reset the phone, no matter when that alarm was set it will fire straight after boot and have details of null.
I have found pages such as this and this, but I am unsure of how to get a calendar object and instantiate it with the original values of each alarm then pass that to my receiver to set the alarm again...
Here is what I have so far.
setAlarm method is used to first create the one-time alarm from calendar values, which are set either via date and time pickers or pre-defined from a choice of spinner (10 minutes, tomorrow etc)
public void setAlarm(String alarmTitle, String alarmNotes, int alarmID) {
// Launch a new intent to save the notification with the title and notes
// passed from onSave
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
alarmIntent.putExtra("Title", alarmTitle);
alarmIntent.putExtra("Notes", alarmNotes);
alarmIntent.putExtra("alarmID", alarmID);
PendingIntent sender = PendingIntent.getBroadcast(this, alarmID,
alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT | Intent.FILL_IN_DATA);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
// Pass alarm calendar to alarm manager
am.set(AlarmManager.RTC_WAKEUP, aCal.getTimeInMillis(), sender);
}
AlarmReceiver
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
// Get a wake lock
wl.acquire();
// Get passed values
Bundle extras = intent.getExtras();
// Set values for use in this class
String nTitle = extras.getString("Title");
String nNotes = extras.getString("Notes");
int uniqueID = extras.getInt("alarmID");
// Set the intent to launch when the notification is clicked and allow the notifications to stack in the one row
Intent resultIntent = new Intent(context, Main.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(context, uniqueID, resultIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
long[] quickBurstsExtended = new long[]{0, 100, 70, 100, 70, 100, 70, 100, 70, 100, 70, 100, 70, 100, 70, 100, 70,
100, 70, 100, 70, 100, 70, 100, 70, 100, 70, 100, 70, 100, 70, 100, 70};
// Notification settings and alert time
Notification builder = new NotificationCompat.Builder(context)
.setContentTitle(nTitle) // Set the title
.setContentText(nNotes) // Set notes
.setSmallIcon(R.drawable.ic_launcher) // Set icon
.setTicker("Did you remember: " + nTitle) // Marquee text (only briefly shown)
.setContentIntent(resultPendingIntent) // Activty that is launched on click
.setWhen(System.currentTimeMillis()) // Fire at the indicated time
.setVibrate(quickBurstsExtended) // Allocate the above vibrate pattern
.setLights(Color.CYAN, 500, 100) // LED lights control
.build();
builder.defaults = Notification.DEFAULT_SOUND;
builder.flags = Notification.FLAG_SHOW_LIGHTS | Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL;
NotificationManager notiManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// Notify the manager when it is time
notiManager.notify(uniqueID, builder);
// Release the wakelock
wl.release();
}
I am storing these reminders in a SQLite database and have included an alarm column which stores the long value of the calendar time, eg: 20140129021559.
I have seen others use a cursor to 'queue' up their alarms on reboot which are sorted by time and will reset everything, but none had enough information for me to actually implement it.
Here is my queueAll() method from my SQLiteAdapter class which is used to populate a listview on the mains screen with all of my current reminders, and sort them based on date (in ascending order) - Could this also be used to fire off the alarms on phone reboot?
public Cursor queueAll() {
String[] columns = new String[]{KEY_ID, KEY_TITLE, KEY_NOTES, KEY_TIME, KEY_DATE, KEY_ALARM_ID, KEY_ALARM};
return db.query(DB_TABLE, columns, null, null, null, null, KEY_ALARM);
}
Any help would be greatly appreciated. As I said I am only just starting out with all of this and if you know of a better way to go about it please let me know.
Sorry for any duplication, but the similar pages that I have found just aren't specific enough to my scenario to help me get over the line.
Regards.
EDIT: I believe I have fixed this now.
For anyone else interested here is what I have done.
I changed my AlarmService class to just be a receiver in the manifest and not the action.BOOT_COMPLETED receiver, and created a seperate class called AutoStart which only handles checking for this flag on start, and then queues up all rows from the SQLite Database and sets the alarms again.
<receiver android:name=".AlarmReceiver"></receiver>
<receiver android:name=".AutoStart">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
Here is the code from AutoStart for now which checks the database and sets the alarms again.
public class AutoStart extends BroadcastReceiver {
SQLiteAdapter db;
@Override
public void onReceive(Context context, Intent intent) {
db = new SQLiteAdapter(context);
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
Cursor cursor = SQLiteAdapter.queueAll();
while (cursor.moveToNext()) {
Date alarmDate = new Date(cursor.getLong(cursor.getColumnIndex(SQLiteAdapter.getKeyAlarm())));
Calendar aCal = Calendar.getInstance();
aCal.setTime(alarmDate);
String title = cursor.getString(cursor.getColumnIndex(SQLiteAdapter.getKeyTitle()));
String notes = cursor.getString(cursor.getColumnIndex(SQLiteAdapter.getKeyNotes()));
int alarmID = cursor.getInt(cursor.getColumnIndex(SQLiteAdapter.getAlarmID()));
AlarmUtils.setAlarm(title, notes, alarmID, context, aCal);
}
}
}
}
My app is now resetting my alarms on a phone reboot and firing them at the correct times.
Cheers!