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);
}
}
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 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);
I want to fetch location every hours in android . For that i use alarm manager and set repeated alarm for every hour and just want to write into file after fix time i.e at 8 AM and 12 PM .
I got a problem in setting alarm manager , while i set for every one hour but it execute in 1/2 hour .
on button click i start service :
serviceButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent myIntent = new Intent(AutoMainActivity.this, TrackerService.class);
pendingIntent = PendingIntent.getService(AutoMainActivity.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, ALARM_TRIGGER_AT_TIME,
3600000, pendingIntent);
//3600000 1hrs
finish();
}
});
And Service Class are as :
Tracker Service.class
String FINAL_STRING;
SharedPreferences pref;
static final int START_TIME = 8;
static final int MID_TIME = 12;
java.util.Date systemDates = Calendar.getInstance().getTime();
int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
if(hour == START_TIME)
{
edit.putString("smsdata", FINAL_STRING);
edit.commit();
//sendSms(START_TAG+pref.getString("smsdata", ""));
edit.putString("smsdata", "");
edit.commit();
}else {
System.out.println("currentdate:"+simpleDateFormat.toString());
System.out.println("current_time:"+currentTime);
Editor edit = pref.edit();
edit.putString("smsdata", pref.getString("smsdata", "")+FINAL_STRING+"#");
edit.commit();
if(hour==MID_TIME)
{
//sendSms(START_TAG+pref.getString("smsdata", ""));
generateNoteOnSD("\n"+START_TAG+pref.getString("smsdata", ""));
edit.putString("smsdata", "");
edit.commit();
System.out.println("mid time");
}
}
When i execute this the service start on every 30min. but i want on every 60min.
First, you really want to use one of the available constants, like INTERVAL_HOUR, with setInexactRepeating().
Second, setInexactRepeating() is inexact. Android reserves the right to flex the times of the alarms to coalesce events with other scheduled inexact alarms.
So, try switching briefly to setRepeating(). If it now works as you expect, your behavior is due to the "inexact" nature of setInexactRepeating().
Also, you can use adb shell dumpsys alarm to examine the scheduled alarms. It may be that you have two alarms scheduled, each going off once per hour.
setInexactRepeating() is the reason why it is not working as you expected. Try following:
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, firstStart, interval, pendingIntent );
In my application I have the functionality to trigger an alarm in 4 scenarios:
Only once for a user-chosen date and time
Daily for the chosen time
Weekly according to chosen date and time
User chosen custom days of the week
I successfully implement the first 3 scenarios by using the following:
Only once:
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, Integer.parseInt(date[0]));
calendar.set(Calendar.MONTH, (Integer.parseInt(date[1])) - 1);
calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(date[2]));
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(time[0]));
calendar.set(Calendar.MINUTE, Integer.parseInt(time[1]));
calendar.set(Calendar.SECOND, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
For daily scheduling:
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(time[0]));
calendar.set(Calendar.MINUTE, Integer.parseInt(time[1]));
calendar.set(Calendar.SECOND, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
For weekly scheduling (as per system date):
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(time[0]));
calendar.set(Calendar.MINUTE, Integer.parseInt(time[1]));
calendar.set(Calendar.SECOND, 0);
//long interval = calendar.getTimeInMillis() + 604800000L;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 7, pendingIntent);
How do I implement weekly alarm scheduling for custom days of the week?
private void scheduleAlarm(int dayOfWeek) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
// Check we aren't setting it in the past which would trigger it to fire instantly
if(calendar.getTimeInMillis() < System.currentTimeMillis()) {
calendar.add(Calendar.DAY_OF_YEAR, 7);
}
// Set this to whatever you were planning to do at the given time
PendingIntent yourIntent;
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 7, yourIntent);
}
private void setUpAlarms() {
scheduleAlarm(Calendar.MONDAY);
scheduleAlarm(Calendar.FRIDAY);
}
Attribution
Source: https://microeducate.tech/repeating-alarm-for-specific-days-of-week-android/ ,
Question Author : Dhruvil Patel(https://stackoverflow.com/users/1367157/dhruvil-patel) , Answer Author : MBH(https://stackoverflow.com/users/2296787/mbh)
I am trying to develop alarm functionality in a my app which runs on a week days specified by user on fixed time. Problem here is that my scheduler running for all days instead of running on specified day . here is the code i wrote for this please help to fix this
Calendar calNow = Calendar.getInstance();
SimpleDateFormat simpDate;
simpDate = new SimpleDateFormat("kk:mm:ss");
if(in_Date==1)
{
calNow.set(Calendar.HOUR_OF_DAY, hourOfDay);
calNow.set(Calendar.MINUTE, minute);
calNow.set(Calendar.SECOND, 0);
calNow.set(Calendar.MILLISECOND, 0);
}
else if(in_Date==2)
{
calNow.set(Calendar.HOUR_OF_DAY, hourOfDay);
calNow.set(Calendar.MINUTE, minute);
calNow.set(Calendar.SECOND, 0);
calNow.set(Calendar.MILLISECOND, 0);
calNow.set(Calendar.DAY_OF_WEEK,in_SelectedDay);
}
etTime.setText(simpDate.format(calNow.getTime()));
Seconds=calNow.getTimeInMillis();
private void setAlarm(){
//etTime.setText(simpDate.format(calNow.getTime()));
Intent intent = new Intent(getBaseContext(), AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(getBaseContext(), RQS_1, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
if(in_Date==1)
{
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Seconds,alarmManager.INTERVAL_DAY,pendingIntent);
}
else if(in_Date==2)
{
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Seconds,1 * 60 * 60 * 1000,pendingIntent);
}
}
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Seconds, AlarmManager.INTERVAL_DAY, pendingIntent);
In this line you set the start time to the user selected day, but then set the interval to INTERVAL_DAY.
You should use INTERVAL_DAY * 7 to make sure it repeats on a weekly basis instead:
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, Seconds, AlarmManager.INTERVAL_DAY * 7, pendingIntent);
Is your alarm getting triggered everyday or every hour ?
I am supposing your in_Date is an indicator to choose daily alarm or for specific days .
My idea-> set the alarm for all days, check your day condition in the alarm receiver .
I have a BroadcastReceiver called AlarmReceiver that Toasts "alarm worked". I'm trying to set up a repeating PendingIntent to trigger AlarmReceiver at 5:45 and 17:30, but I see "alarm worked" after few seconds of starting the app. Why is the PendingIntent getting sent immediately?
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Calendar cal1 = Calendar.getInstance();
cal1.set(Calendar.HOUR_OF_DAY, 05);
cal1.set(Calendar.MINUTE, 45);
cal1.set(Calendar.SECOND, 00);
Calendar cal2 = Calendar.getInstance();
cal2.set(Calendar.HOUR_OF_DAY, 17);
cal2.set(Calendar.MINUTE, 30);
cal2.set(Calendar.SECOND, 00);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(),cal2.getTimeInMillis(), pi);
Toast.makeText(this, "Alarm set", Toast.LENGTH_LONG).show();
}
}
AlarmReceiver:
public class AlarmReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Alarm worked.", Toast.LENGTH_LONG).show();
}
but I see "alarm worked" after few seconds of starts of my app.
I believe you are receiving the first alarm just fine.
But you believe it is not repeating. This wrong, it will repeat... once every ~43 years. You are using the third parameter of setRepeating incorrectly, try:
Calendar cal1 = Calendar.getInstance(); // Now
cal1.add(Calendar.SECONDS, 5); // Change to five seconds from now
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
cal1.getTimeInMillis(),
10000, /* Repeat every 10 seconds */
pi);
The third parameter is an interval. This code creates an alarm that goes off in 5 seconds, then repeats every 10 seconds. By using cal2 you are accidentally setting the interval to almost 43 years.
To set two different alarms use:
Calendar cal1 = Calendar.getInstance();
cal1.set(Calendar.HOUR_OF_DAY, 05);
cal1.set(Calendar.MINUTE, 45);
cal1.set(Calendar.SECOND, 00);
Calendar cal2 = Calendar.getInstance();
cal2.set(Calendar.HOUR_OF_DAY, 17);
cal2.set(Calendar.MINUTE, 30);
cal2.set(Calendar.SECOND, 00);
// Test if the times are in the past, if they are add one day
Calendar now = Calendar.getInstance();
if(now.after(cal1))
cal1.add(Calendar.HOUR_OF_DAY, 24);
if(now.after(cal2))
cal2.add(Calendar.HOUR_OF_DAY, 24);
// Create two different PendingIntents, they MUST have different requestCodes
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent morningAlarm = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0);
PendingIntent eveningAlarm = PendingIntent.getBroadcast(getApplicationContext(), 1, intent, 0);
// Start both alarms, set to repeat once every day
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), DateUtils.DAY_IN_MILLIS, morningAlarm);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal2.getTimeInMillis(), DateUtils.DAY_IN_MILLIS, eveningAlarm);
As Sam's post says, you aren't using the right triggerAtMillis and intervalMillis. I think you are telling it to trigger at 5 am on the current day, which is likely in the past, in which case the documentation says that the
Calendar cal1 = Calendar.getInstance();
cal1.add(Calendar.HOUR, 5);
cal1.add(Calendar.MINUTE, 45);
long interval = 17 * 60 * 60 * 1000; // 17 hours converted to milliseconds
interval += 30 * 60 * 1000; // 30 minutes converted to milliseconds
Intent intent = new Intent(this, TestAlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal1.getTimeInMillis(), interval, pi);
is probably what you want to do instead.
EDIT (more explanation):
cal1.add(Calendar.HOUR, 5); takes the current date and time and increases it by 5 hours, so the result is that the repeating PendingIntent will begin 5 hours and 45 minutes from the current time on this date. and the interval says that it will send the second and subsequent PendingItents every 17 hours and 30 minutes from then (where then is 5 hours and 45 minutes from now).
If you want to set the start to be 5:45 am, but don't want it to be sent immediately (unless it happens to be exactly 5:45 am at the moment). then you will want to set do:
cal1.set(Calendar.HOUR, 5);
cal1.set(Calendar.MINUTE, 45);
cal1.set(Calendar.SECOND, 0);
// Current time is after 5:45 am, don't start until tomorrow at 5:45
if (Calendar.getInstance().after(cal1))
cal1.add(Calendar.DAY_OF_YEAR, 1)
Alternatively, you can compute the interval from that time to decide when it would be triggered next assuming it had already been started at 5:45, but that would take a bit more work to compute.