I am trying to send a notification everyday at 6 AM using Android AlarmManager. The notification works for one time and doesn't work for other days.
public class AlarmMsg extends WakefulBroadcastReceiver {
// set the alarm
public void setAlarm(Context context) {
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmIntent = PendingIntent.getBroadcast(context, 0, new Intent(context, AlarmMsg.class), 0);
Calendar firingCal = Calendar.getInstance();
Calendar currentCal = Calendar.getInstance();
firingCal.set(Calendar.HOUR, 6); // hour
firingCal.set(Calendar.MINUTE, 0);
firingCal.set(Calendar.SECOND, 0);
long intendedTime = firingCal.getTimeInMillis();
long currentTime = currentCal.getTimeInMillis();
if (intendedTime >= currentTime) {
// set from today
alarmManager.setRepeating(AlarmManager.RTC, intendedTime, AlarmManager.INTERVAL_DAY, alarmIntent);
} else {
// set from next day
firingCal.add(Calendar.DAY_OF_MONTH, 1);
intendedTime = firingCal.getTimeInMillis();
alarmManager.setRepeating(AlarmManager.RTC, intendedTime, AlarmManager.INTERVAL_DAY, alarmIntent);
}
}
and create the notification :
#Override
public void onReceive(Context context, Intent intent) {
// notification builder
}
and in my main activity I just call the setAlarm like this:
new AlarmMsg().setAlarm(getApplicationContext());
this shows a notification at 6AM but it only shows 1 notification and it does not repeat for the following days. I want the notification to show every day at 6AM. Any ideas?
If you receive alarm once then you are on the right track, just remember to use AlarmManager.RTC_WAKEUP alarm type so the device will wake up when goes off. Also consider using setInexactRepeating if your alarm isn't critical.
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
Related
I have an AlarmManager that I call at the end of every day, ie 23.59PM, to do some stuff for the new day. (Its called, NewDayReceiver.class.) It repeats every day.
I also set a broadcast receiver that will run the alarm on reboot. It all works fine.
However, if the phone is off at the end of the day, the alarm for that day is not called. When the phone is turned back on, on boot the alarm is set again, however its set for the end of the new day. It comes out, that the alarm for that day was never called. For example, if its off Sunday night, on Monday morning the phone is turned on but the alarm hasn't been called. It will only be called Monday night?
How can I do it, that on the boot broadcast receiver, I can check if the alarm was called for that day, and if it wasn't set the alarm to go off right away.
I hope its clear.
Here is my alarm for every day.
Intent intent = new Intent(this, NewDayReceiver.class);
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
if(!calendar.before(Calendar.getInstance())) {
// Repeat every 24 hours
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24*60*60*1000, pendingIntent);
Log.d(TAG, "New day alarm set for:" + calendar.getTime() + " and will repeat every day");
}
Here is my BroadcastReceiver, that I call on boot:
public class BootBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "999.BootBroadcastReceiver";
#Override
public void onReceive(Context pContext, Intent intent) {
newDayAlarm(pContext);
newWeekAlarm(pContext);
}
private void newWeekAlarm(Context context) {
Intent intent = new Intent(context, NewWeekReceiver.class);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 55, intent, 0);
// real for end of week
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
if(!calendar.before(Calendar.getInstance())) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Log.d(TAG, "New week alarm set for:" + calendar.getTime());
}
}
}
I am setting Alarm using Alarm Manager And setting this Alarm By Picking Values from SQlite Database.The Alarm is working fine for future Alarms but the problem is when I open the Activity in which Alarm Function is Called, The Alarm Start ringing for All Previous Times. How Should I solve this problem ?
Here is My Alarm Function
void Alaramset()
{
Cursor cursor=mydb.getAllData();
if (cursor.moveToFirst())
{
do{
String alarm1 = cursor.getString (cursor.getColumnIndex(DBHelper.ALARM_COLUMN_REMINDER1));
int id = Integer.parseInt(cursor.getString(cursor.getColumnIndex(DBHelper.ALARM_COLUMN_ID)));
int minute=Integer.parseInt (alarm1.substring(3, 5));
int hr=Integer.parseInt(alarm1.substring(0, 2));
Intent myIntent = new Intent(getActivity(), MyAlaramService.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent pendingIntent = PendingIntent.getService(getActivity(), id, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getActivity().getSystemService(Context.ALARM_SERVICE);
// Toast.makeText(getActivity(), ""+minute+" : "+hr, 300).show();
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, hr);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
while (cursor.moveToNext());
}
}
It looks like you are scheduling alarms that happen in the past.
Any alarm scheduled in the past will trigger immediately.
A simple solution would be to schedule past alarms for the next day.
Calendar now = Calendar.getInstance();
now.setTimeInMillis(System.currentTimeMillis());
if (calendar.before(now) {
// alarm has already happened. schedule it for tomorrow
calendar.add(Calendar.Date, 1);
}
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
My application creates an alarm that repeats every day. Since it is not possible to know if an alarm is already registered, I create the alarm every time the application is launched.
Here is the function that is called at the beginning of the main activity (inside onCreate()):
public static void setAlarm(Context context) {
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Calendar firingCal = Calendar.getInstance(TimeZone.getTimeZone("Europe/Paris"));
Calendar currentCal = (Calendar)firingCal.clone();
Random rnd = new Random();
// Each day between 1:00 AM and 1:30 AM (some jitter added)
firingCal.set(Calendar.HOUR_OF_DAY, 1);
firingCal.set(Calendar.MINUTE, rnd.nextInt(30));
firingCal.set(Calendar.SECOND, 0);
long intendedTime = firingCal.getTimeInMillis();
long currentTime = currentCal.getTimeInMillis();
if (intendedTime >= currentTime) {
//set from today
alarmManager.setInexactRepeating(AlarmManager.RTC, intendedTime, AlarmManager.INTERVAL_DAY, pendingIntent);
} else {
//set from next day
firingCal.add(Calendar.DAY_OF_MONTH, 1);
intendedTime = firingCal.getTimeInMillis();
alarmManager.setInexactRepeating(AlarmManager.RTC, intendedTime, AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
Is it OK to recreate the alarm each time the application is launched? Should I use some flags on the PendingIntent (like update or cancel existing PendingIntent)?
Thanks!
Update: is it a problem if I use flag 0 instead of PendingIntent.FLAG_UPDATE_CURRENT from a performance perspective?
I have this alarm manager which I want to fire at 6 AM everyday. I call the class notification, when the app is first launched and hence, it sets an repeating alarm for 6 AM every day(repeatedly).
The alarm manager works fine when the user installs(and runs the app first time) from 6 to 9 AM, however if the user runs the app for the first time after 9 AM, I'm supposed to add a day and fire the alarm the next day at 6AM. On doing so, (changing the date to the next day), the alarm gets fired at a random time, around 10 PM (That's a huge difference). Here's my code"
public notification(Context context) {
this.context=context;
Intent appstart=new Intent(context,appstartreceiver.class);
PendingIntent pi=PendingIntent.getBroadcast(context,0,appstart,PendingIntent.FLAG_UPDATE_CURRENT); // For appstart in the morning
AlarmManager alarmManager = (AlarmManager)context.getSystemService(context.ALARM_SERVICE);
Calendar currentCal=Calendar.getInstance();
Calendar startapp = Calendar.getInstance();// FOr app start in the morning
startapp.set(Calendar.HOUR_OF_DAY,6);
startapp.set(Calendar.MINUTE, 0);
startapp.set(Calendar.SECOND, 0);
long currentTime = currentCal.getTimeInMillis();
int diff=(int)(currentTime-startapp.getTimeInMillis())/(1000*60*60);
if (diff<3)
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,startapp.getTimeInMillis(),1000*24*60*60,pi);
else {
startapp.add(Calendar.HOUR_OF_DAY, 24);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, startapp.getTimeInMillis(), 1000 * 24 * 60 * 60, pi);
}
}
Replace your code with below code...this will fire everyday at 6 am. It may helps you.
public void notification(Context context) {
Intent intent = new Intent(this, appstartreceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 99, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 6);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
long startUpTime = calendar.getTimeInMillis();
// To avoid firing the alarm if the time is passed while setting
if (System.currentTimeMillis() > startUpTime) {
startUpTime = startUpTime + 24 * 60 * 60 * 1000;
}
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, startUpTime, 24 * 60 * 60 * 1000, pendingIntent);
}
You could try adding a day
if (calendar.before(Calendar.getInstance())) {
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
....// your code
That way it will fire everyday at the set time.
Try commonwares's wakeful intent service,it may help.
public class DailyListener implements AlarmListener {
public void scheduleAlarms(AlarmManager mgr, PendingIntent pi, Context context) {
// every day at scheduled time
Calendar calendar = Calendar.getInstance();
// if it's after or equal 6 am schedule for next day
if (Calendar.getInstance().get(Calendar.HOUR_OF_DAY) >= 6) {
calendar.add(Calendar.DAY_OF_YEAR, 1);
}
calendar.set(Calendar.HOUR_OF_DAY, 6);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
mgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
}
}
i created alarm demo . In that demo i am repeating an alarm . I have one problem in my demo . My alarm called service even if time passed . I am setting 16:08:00 time and called that alarm so it called my alarm service after passed that time.Please help me to stop this criteria.
AlarmManager alarmManager = (AlarmManager)ctx.getSystemService(ctx.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 16);
calendar.set(Calendar.MINUTE, 8);
calendar.set(Calendar.SECOND, 0);
PendingIntent pi = createPendingIntent(ctx);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24*60*60*1000, pi);
CreatePendingIntent Method
private static PendingIntent createPendingIntent(Context context)
{
Intent myIntent = new Intent(context, MyAlarmService.class);
return PendingIntent.getService(context,0, myIntent, 0);
}
When setting an alarm to past time, the alarm immediately pops up.
Simply check if the current time is bigger than the alarm time. If so, add 24 hours to the alarm time and set the alarm.:
long timeToAlarm = calendar.getTimeInMillis();
if (calendar.getTimeInMillis() < System.currentTimeMillis())
{
timeToAlarm += (24*60*60*1000);
}
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, timeToAlarm, 24*60*60*1000, pi);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24*60*60*1000, pi);
if you used the above code the alarm repeats at the 24*60*60*1000 interval time.If you don't want to repeat the alarm then use the bellow code
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pi);
the above code will cal the alarm only onetime.