I've read about every similar question on here but cannot find an answer, so please forgive me if this has been answered before, I really tried to search.
I'm setting up an alarm to show a notification after a certain time. The time logic is definitely solid, I can tell by my log output, this is not the problem.
I create a Pending intent like so:
Intent alarmIntent = new Intent(c, AlarmReceiver.class);
alarmIntent.putExtra("title", name);
alarmIntent.putExtra("location", building);
PendingIntent pi = PendingIntent.getBroadcast(c, 0, alarmIntent, 0);
and then set the alarm to fire after millis milliseconds. In this instance, millis is 407603959 according to my log statements. It definitely should not be firing after one second.
alarm.set(AlarmManager.RTC_WAKEUP, millis, pi);
Log.i("Alarm", "Alarm: " + name + " is set for: "
+ untilAlarm.getDays() + " days, " + untilAlarm.getHours() + " hours, "
+ untilAlarm.getMinutes() + " minutes from now. Or, " + millis
+ " milliseconds");
It appears as though my PendingIntent is being started before the alarm is even set. I tried blocking an alarm from being created like so:
Intent alarmIntent = new Intent(c, AlarmReceiver.class);
alarmIntent.putExtra("title", name);
alarmIntent.putExtra("location", building);
PendingIntent pi = PendingIntent.getBroadcast(c, 0, alarmIntent,
PendingIntent.FLAG_ONE_SHOT);
if (!name.equals("test") {
alarm.set(AlarmManager.RTC_WAKEUP, millis, pi);
//Log statement...
}
and the alarm for test is still triggered, but the log statement is not printed to the console, meaning alarm.set was never called. The intent is still fired, and a notification is shown with the title "test".
Why is my PendingIntent being launched before the alarm is fired?
You are using an alarm type of AlarmManager.RTC_WAKEUP, which will set the alarm to start at a specified time, in your case millis.
To set the alarm to start at a certain amount of time in the future, you need to either use one of these types of elapsed-time alarms:
ELAPSED_REALTIME
Alarm time in SystemClock.elapsedRealtime() (time since boot,
including sleep). This alarm does not wake the device up; if it goes
off while the device is asleep, it will not be delivered until the
next time the device wakes up.
ELAPSED_REALTIME_WAKEUP
Alarm time in SystemClock.elapsedRealtime() (time since boot,
including sleep), which will wake up the device when it goes off.
Or use an RTC or RTC_WAKEUP with the current time plus the time to wait, like:
alarm.set(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis() + millis, pi);
Related
I'm working on an event planner for Android (learning purposes), and want each event to have it's own reminder. I've got the alarms working and they successfully trigger and know how to check if the alarms exist, but I'm unable to find out how to get the time for each alarm.
I've managed to identify if the alarm exists using:
Intent i = new Intent(getApplicationContext(), NotificationReceiver.class);
pIntent = PendingIntent.getBroadcast(getApplicationContext(), (int) id, i, PendingIntent.FLAG_NO_CREATE);
And I've tried using
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar test = Calendar.getInstance();
test.setTimeInMillis(am.getNextAlarmClock().getTriggerTime());
Log.d(TAG, "getReminder: TRIGGER: " + test.getTime());
But the time displayed there doesn't even match any of my alarms when testing. Also this doesn't allow me to identify which event the alarm belongs to anyway.
This is where I create the reminders.
public void makeReminder(String event, long reminder){
Log.d(TAG, "makeReminder: Started");
Intent i = new Intent (getApplicationContext(), NotificationReceiver.class);
i.putExtra("id", event); // eventID
i.putExtra("reminder", reminder); // reminderKey
i.putExtra("reminderTime", reminderCal.getTimeInMillis()); // actual time for the reminder
i.putExtra("message", "You have an upcoming event on " + dateTimeFormat.format(startCal.getTime()));
i.putExtra("name", eventName);
i.putExtra("channel", "event");
PendingIntent nIntent = (PendingIntent) PendingIntent.getBroadcast(
getApplicationContext(),
(int)reminder, i,
PendingIntent.FLAG_CANCEL_CURRENT
);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, reminderCal.getTimeInMillis(), nIntent);
Log.d(TAG, "makeReminder: reminder set for " + reminderCal.getTime());
Log.d(TAG, "makeReminder: reminderID: " + reminder);
}
I'm not sure how to proceed to get the time, but I'm hoping that it would be possible to get the triggertime with the reminderKey or alternatively fetching the reminderTime from the intent before the event actually gets triggered. The point is for users to see if there's an alarm set, when it is and then I know how to cancel or change the alarm. Just can't find a good way of displaying it.
Hopefully something that's simple to achieve, that I've overlooked :/ but can't seem to solve this.
You can't get this information from AlarmManager. If you need this information, you will need to save it in some persistent storage (SQLite database, SharedPreferences, File, etc.) and manage it yourself.
I've got a problem with the AlarmManager. I'm able to set up the Alarm with this code
private void setAlarm(long when) {
Intent intent = new Intent(NoteActivity.this, AlarmReceiver.class);
intent.putExtra("ID", note.getId());
AlarmManager manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, PendingIntent.getBroadcast(NoteActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT));
Toast.makeText(getApplicationContext(),"Reminder set up", Toast.LENGTH_SHORT).show();
}
This code works well if I set long when = 5 * 1000; \\For example 5secs later, but if I use this code
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
long selectedDate = date.getTime();
long timeSince1970 = System.currentTimeMillis();
long timeForAlarm = selectedDate - timeSince1970;
Intent intent = new Intent(NoteActivity.this, AlarmReceiver.class);
intent.putExtra("ID", note.getId());
AlarmManager manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeForAlarm, PendingIntent.getBroadcast(NoteActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT));
Toast.makeText(getApplicationContext(),"Reminder set for "+calendar.getTime().toString(), Toast.LENGTH_SHORT).show();
my alarm triggerd 2secs later. What I'm doing wrong? :/
I've tried AlarmManager.ELAPSED_REALTIME_WAKEUP and AlarmManager.RTC_WAKEUP but nothing changed.
Please do not check my question as duplicated. I didn't find something to try that solved my problem.
Assuming that you are working in Android Studio (if not - you must switch), click F1 while your text pointer is on set method and read description of AlarmManager::set.
Note: Beginning in API 19, the trigger time passed to this method is
treated as inexact: the alarm will not be delivered before this time,
but may be deferred and delivered some time later. The OS will use
this policy in order to "batch" alarms together across the entire
system, minimizing the number of times the device needs to "wake up"
and minimizing battery use. In general, alarms scheduled in the near
future will not be deferred as long as alarms scheduled far in the
future.
Instead of set use setExact
manager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeForAlarm, PendingIntent.getBroadcast(NoteActivity.this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT));
I am setting alarm with an interval of 2 hours. It work very perfect but the problem is, at the time of set it trigger the alarm.
It don't have to trigger alarm at time of set rest is all ok.
Intent _myIntent = new Intent(activity, MyReceiverStartPush.class);
_myIntent.putExtra("msg", "Feed");
PendingIntent _myPendingIntent = PendingIntent.getBroadcast(
activity, 0, _myIntent, 0);
AlarmManager _myAlarmManager = (AlarmManager) activity
.getSystemService(Service.ALARM_SERVICE);
_myAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), (AlarmManager.INTERVAL_HOUR)
* 2, _myPendingIntent);
Instead of using System.currentTimeMillis() (which is the reason) you should use System.currentTimeMillis() + 2H there
i have a problem with triggering the multiple alarm at first time , here is my code
it is launcher activity where i write the following code ::
**onCreate Method :
// Calling Method setNextAlarm two times..with different id and time
setNextAlarm(0,60000);
setNextAlarm(1,120000);
and the setNextAlarm is here ::
private void setNextAlarm(int id,long time) {
AlarmManager mgr = (AlarmManager) TestAct.this
.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(TestAct.this, OnBootReceiver.class);
i.putExtra("id", id);
Log.e("Firing up next alarm in "+id,""+time/(60*1000) +"minutes");
PendingIntent pi = PendingIntent.getBroadcast(TestAct.this, id, i,PendingIntent.FLAG_ONE_SHOT);
mgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, pi);
}
when i run this code it calls the onBootReceiver which is our Broadcast receiver class.
So My question is ::
After defining the different time and id in this method
setNextAlarm(0,60000);
setNextAlarm(1,120000);
why it fires at same time ? Except the first time it runs fine at fixed interval.
this is my onBootReceiver class's onReceive method
Bundle b = intent.getExtras();
int id = b.getInt("id");
if(id==1){
PERIOD=300000;
}else{
PERIOD=120000;
}
Log.e("OnBootReceiver"," Calling"+id+" in "+PERIOD/60000 + "minutes");
AlarmManager mgr=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i=new Intent(context, OnAlarmReceiver.class);
i.putExtra("id", id);
PendingIntent pi=PendingIntent.getBroadcast(context, id,i, 0);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime()+60000,
PERIOD,
pi);
Thanks.
in OnBootReceiver
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 60000, PERIOD, pi);
here is change
i set
SystemClock.elapsedRealtime() + 60000 for id = 0
and set the
SystemClock.elapsedRealtime() + 120000 for id = 1
and the problem resolved.
But i am still waiting for Better Explanation.
i found little information here about SystemClock.elapsedRealtime()
elapsedRealtime() is counted in milliseconds since the system was booted, including deep sleep. This clock should be used when measuring time intervals that may span periods of system sleep.
http://developer.android.com/reference/android/os/SystemClock.html
I am currently trying to write alarm manager that will make an alarm go off within a specified period of time, daily. First I check to see if the user has had an alarm set for that for that day:
if ((User.getReminderTime(Home.this) > 0)
&& (dt.getDate() != today.getDate() || dt.getDay() != today
.getDay())) {
AppointmentManager.setFutureAppointmentCheck(this
.getApplicationContext());
User.setLongSetting(this, "futureappts", today.getTime());
}
Then I go and set the actual alarm to go off between 12 and 12:10 of the next day:
public static void setFutureAppointmentCheck(Context con) {
AlarmManager am = (AlarmManager) con
.getSystemService(Context.ALARM_SERVICE);
Date futureDate = new Date(new Date().getTime() + 86400000);
Random generator = new Random();
futureDate.setHours(0);
futureDate.setMinutes(generator.nextInt(10));
futureDate.setSeconds(0);
Intent intent = new Intent(con, FutureAppointmentReciever.class);
PendingIntent sender = PendingIntent.getBroadcast(con, 0, intent,
PendingIntent.FLAG_ONE_SHOT);
am.set(AlarmManager.RTC_WAKEUP, futureDate.getTime(), sender);
}
Now I setup a test environment for this to go off every two minutes and it seems to be working fine, however when I deploy to an actual device, the reciever does not seem to be recieving the alarms. I thought it might be an issue with the device being asleep, so I added the power manager. But it still does not work:
PowerManager pm = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, "keepAlive");
wl.acquire();
setFutureAppointments(context.getApplicationContext());
AppointmentManager.setFutureAppointmentCheck(context
.getApplicationContext());
User.setLongSetting(context.getApplicationContext(), "futureappts",
new Date().getTime());
wl.release();
Anyone see anything I am doing blatantly wrong or am I going about this incorrectly? thanks for any and all help.
I usually do something more along the lines of:
Intent i = new Intent(this, MyService.class);
PendingIntent pi = PendingIntent.getService(this, 0, i, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.cancel(pi); // cancel any existing alarms
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + AlarmManager.INTERVAL_DAY,
AlarmManager.INTERVAL_DAY, pi);
This way, you don't have to worry about re-setting the AlarmManager in your Service.
I usually run this bit of code when my app starts (onResume in my main activity) and in a BroadcastReceiver that is set up to receive BOOT_COMPLETED.
I've written a guide on creating Services and using the AlarmManager, which is based on my own experience and a few tips & tricks I picked off from watching a Google I/O talk. If you're interested, you can read it here.
To answer your question below, all I can do is quote the docs:
public void setInexactRepeating (int type, long triggerAtTime, long interval, PendingIntent operation)
Schedule a repeating alarm that has inexact trigger time requirements; for example, an alarm that repeats every hour, but not necessarily at the top of every hour. These alarms are more power-efficient than the strict recurrences supplied by setRepeating(int, long, long, PendingIntent), since the system can adjust alarms' phase to cause them to fire simultaneously, avoiding waking the device from sleep more than necessary.
Your alarm's first trigger will not be before the requested time, but it might not occur for almost a full interval after that time. In addition, while the overall period of the repeating alarm will be as requested, the time between any two successive firings of the alarm may vary. If your application demands very low jitter, use setRepeating(int, long, long, PendingIntent) instead.
In conclusion, it's not very clear. The docs only say that the alarm "may vary". However, it should be important for you to know that the first trigger might not occur for almost a full interval after that time.
This is working, this will shoot alarm after every 5 seconds
private void setRecurringAlarm() {
Logger.d(IConstants.DEBUGTAG, "Setting Recurring Alarm");
Calendar updateTime = Calendar.getInstance();
updateTime.set(Calendar.SECOND, 5);
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
PendingIntent recurringDownload = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarms.cancel(recurringDownload);
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), 1000 * 5, recurringDownload); //will run it after every 5 seconds.
}