Is it possible to call receiver only on start of every new hour? I have running service and I need to call receiver only when the time changes from for example: five o'clock to six o'clock, etc.? Is there any way how can I do it?
You will need to use an AlarmManager. Then schedule the times you want it to notify you. Google for more examples.
UPDATE:
What you can do is wake it up at the next hour, at 8.00 if time is 7.30 . Then shedule it for an hourly wake up the next time it starts.
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR,c.get(Calendar.HOUR)+1);
c.getTimeInMillis(); // use this in alarmmanager for the first time, 60*60*1000 from next time
You can use a combination of GregorianCalendar and an AlarmManager for this. You basically add 1 hour to the current time and then round downwards to the nearest hour. See an example here:
long UPDATE_INTERVAL = 60 * 60 * 1000; // 1 hour in milliseconds.
Calendar c = new GregorianCalendar(); // Get current time
c.add(Calendar.HOUR_OF_DAY, 1); // Add one hour to the current time.
// Set minutes, second, millisecond to 0, such that we ensure that an update is done
// at the end of the hour.
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
final AlarmManager alarm = (AlarmManager) context.getSystemService(ALARM_SERVICE);
// Set an alarm, starting from the end of the current hour, every hour, to execute
// the update service.
// pIntent is the pending intent you would like activate.
alarm.setRepeating(AlarmManager.RTC, c.getTimeInMillis(), UPDATE_INTERVAL, pIntent);
I assume you know how to call the receiver.
Related
I'm new to android and using alarmManager and I was wondering if there is a way to set an alarm in android that triggers for example every monday until a certain specific date. Like this :
Start date 10/09/15
Remind me something every monday at 2:30 pm
Until
End date 11/09/15
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 14);
calendar.set(Calendar.MINUTE, 30);
int weekInMillis = 7 * 24 * 60 * 60 * 1000;
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
weekInMillis, PendingIntent.getBroadcast(context, 0, new Intent(context, ReminderAlarmWakefulBroadcastReceiver.class), PendingIntent.FLAG_UPDATE_CURRENT));
Above code snippet sets an alarm for 2:30 PM that repeats itself every week. Tweak calendar for varying the time at which the alarm goes off. For example, the coming Monday.
When the alarm goes off, it sends a broadcast which will be received by ReminderWakefulBroadcastReceiver, a custom receiver containing the code that you want to run every Monday at 2:30 PM. This code should also check whether it is time to cancel the alarm and if it is, the following code cancels it:
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(PendingIntent.getBroadcast(context, 0, new Intent(context, ReminderAlarmWakefulBroadcastReceiver.class));
References:
AlarmManager, Scheduling Repeating Alarms, PendingIntent
If you know how to setup an Alarm, the solution is quite simple:
1) At the time you setup the Alarm, calculate the maximum timestamp you want it to run, and save it as a local preference.
2) Then in the Alarm code itself, each time it is triggered you can make a first test to see if the current timestamp is before or after your limit preference saved at first time.
3) If reached, then cancel the Alarm as #karthik said. If not, keep your code going...
I need to the Android app to send notification to remind users at 8am, 3pm and 8pm every day. So I use the following three lines in onCreate() of the MainActivity, when the application starts. However, when I run the app, all three notification are coming at once instead of at the wanted time.
setRepeatedNotification(1,8,0,0);
setRepeatedNotification(2,15,0,0);
setRepeatedNotification(3,20,0,0);
Why is that? I also attach the setRepeatedNotification function here. Thank you!
private void setRepeatedNotification(int ID, int hh, int mm, int ss) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent alarmIntent = new Intent(MainActivity.this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, ID, alarmIntent, 0);
Calendar calendar = Calendar.getInstance();
// calendar.set();
calendar.set(Calendar.HOUR_OF_DAY, hh);
calendar.set(Calendar.MINUTE, mm);
calendar.set(Calendar.SECOND, ss);
// Clear previous everyday pending intent if exists.
if (null != mEverydayPendingIntent) {
alarmManager.cancel(mEverydayPendingIntent);
}
mEverydayPendingIntent = pendingIntent;
alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mEverydayPendingIntent);
}
Here is the updated code:
private void setRepeatedNotification(int ID, int hh, int mm, int ss) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent alarmIntent = new Intent(StartActivity.this, AlarmReceiver.class);
alarmIntent.putExtra("ID",ID);
Log.d("setRepeatedNotification", "ID:" + ID);
PendingIntent pendingIntent = PendingIntent.getBroadcast(StartActivity.this, ID, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
Calendar now = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hh);
calendar.set(Calendar.MINUTE, mm);
calendar.set(Calendar.SECOND, ss);
//check whether the time is earlier than current time. If so, set it to tomorrow. Otherwise, all alarms for earlier time will fire
if(calendar.before(now)){
calendar.add(Calendar.DATE, 1);
}
mEverydayPendingIntent = pendingIntent;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mEverydayPendingIntent);
}
I see two potential problems with your setup with AlarmManager. The first arises when the device goes to sleep.
From AlarmManager's documentation:
If an alarm is delayed (by system sleep, for example, for non _WAKEUP alarm types), a skipped repeat will be delivered as soon as possible. After that, future alarms will be delivered according to the original schedule; they do not drift over time. For example, if you have set a recurring alarm for the top of every hour but the phone was asleep from 7:45 until 8:45, an alarm will be sent as soon as the phone awakens, then the next alarm will be sent at 9:00.
As you can see, if you've set an alarm and the device has gone to sleep, without using AlarmManager.RTC_WAKEUP there could be a long delay depending on how long the device has been in sleep for. If you've never touched your device and no other alarms caused a wakeup, it could cause all your alarms to stack up upon the next hour that the device is awake for.
Another potential issue I see is that you are retrieving a Calendar instance representing the time right now, but then setting the hour, minute and second by yourself. The current day and the current year have been automatically populated from the current time.
Again, from the documentation (emphasis mine):
If the stated trigger time is in the past, the alarm will be triggered immediately, with an alarm count depending on how far in the past the trigger time is relative to the repeat interval.
In this case, if your method was invoked past 8 pm on the given day, calendar.getTimeInMillis() will return a timestamp in the past for all three alarms, causing them to be triggered immediately since 8 am, 3 pm and 8 pm have already past in that day. In this case, you must first evaluate whether the current time is past the alarm interval you are trying to set and add 1 day more onto the time you are setting to make sure the alarm has been set in the future.
Can someone please explain why the following code is working (ie. first alarm fires with 20 second delay):
Calendar cal = Calendar.getInstance();
cal.add (Calendar.SECOND,20);
am = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC, cal.getTimeInMillis(), 20000, PendingIntent pi);
while the following is NOT (ie. first alarm fires instantly):
am = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC, SystemClock.elapsedRealtime() + 20000, 20000, PendingIntent pi);
SystemClock.elapsedRealtime()[1] returns the number of milliseconds since boot.
cal.getTimeInMillis()[2] returns number of millisecond since UNIX Epoch (1970/01/01)... based on your code.
The first code block is actually scheduling an alarm for 20 seconds in the future.
The second code block is actually scheduling an alarm in the distant past (unless you booted up your phone 1st Jan 1970!) and the time for the alarm to be run has already passed. The alarm hasn't run yet though, so it runs it now that it's flagged the time as elapsed.
[1] http://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtime()
[2] http://developer.android.com/reference/java/util/Calendar.html#getTimeInMillis()
I have service run in background.
I want to call this service at specific interval.
if user provide values 10, 20, 30 than service should call after 10 min,20 min and 30 min receptively.
How can I do above thing?
AlarmManager will help you :)
It allows you to set up a schedule to launch your application's components during the specified time range
Update
To instantiate an AlarmManager that will go into play at the specific period after it's instantiating, configure it with setRepeating() method and PERIOD parameter added to SystemClock.elapsedRealime():
AlarmManager mgr = (AlarmManager)getSystemService(ALARM_SERVICE);
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + PERIOD, PERIOD, pi); // Here PERIOD is a value specified by you as PendingIntent object
You can set an Alarm to have an Intent fired at specific interval. You can also set an inexact alarm if it is not critical that the alarm runs at the precise time.
Calendar startTime = Calendar.getInstance();
startTime.set(Calendar.HOUR_OF_DAY, 10);
startTime.set(Calendar.MINUTE, 20);
startTime.set(Calendar.SECOND, 25);
Intent dailyQuotes = new Intent(getActivity(), DailyQuotesService.class);
AlarmManager am = (AlarmManager)getActivity().getSystemService(Context.ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(getActivity(), 0, dailyQuotes, 0);
am.setInexactRepeating(AlarmManager.RTC_WAKEUP, startTime.getTimeInMillis(), 30000, pi);
here is my code and it call my service exactly on specified time. and then is repeated every 30 secs.
I am starting my alarm at 8am using below code, repeating at every 1min. I want to stop this alarm repeating at 12pm. I am starting alarm like this:
AlarmManager manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
PendingIntent loggerIntent1 = PendingIntent.getBroadcast(this, 0,new Intent(this,AlarmReceiver.class), 0);
Calendar timeOff9 = Calendar.getInstance();
timeOff9.set(Calendar.HOUR_OF_DAY, 08);
timeOff9.set(Calendar.MINUTE, 00);
timeOff9.set(Calendar.SECOND, 00);
long duration = interval * 60 * 1000;
manager.setRepeating(AlarmManager.RTC_WAKEUP,timeOff9.getTimeInMillis(), duration, loggerIntent1);
and stopping with this code:
Calendar timeOff = Calendar.getInstance();
timeOff.set(Calendar.HOUR_OF_DAY,12);
timeOff.set(Calendar.MINUTE,00);
timeOff.set(Calendar.SECOND, 00);
manager.set(AlarmManager.RTC_WAKEUP,timeOff.getTimeInMillis(), loggerIntent1);
manager.cancel(loggerIntent1);
loggerIntent1.cancel();
but the code for stopping causes the app to work the wrong way.
I am writing the code to stop alarm right after first alarm. is it the problem?
Do I need to write another alarm. Please guide.
Maybe there is another logic you could give a try?
Imagine this, carry on with your first portion of code where you trigger an intent for every duration.
But inside your AlarmReceiver.class, that will be the one checking current time, and do the AlarmManager.cancel() when the time is over 12pm.