Call a method every x minutes - java

currently I have a application which can send notifications, I would like this application to be able to send these notifications automatically every x minutes (for example, 15 minutes is the default). The app may or may not be currently running when this notification should be sent.
After some reading, I've determined that an AlarmManager would be used here, but I cannot figure out how to call a method from it. I already have the notification code, I just need a way to call it every x minutes.
I'm very new to this, this is my first practice app (having experience in C#, but little in Java).
Thanks, David.

You might want to consider something like this:
Intent intent = new Intent(this, MyService.class);
PendingIntent pintent = PendingIntent.getService(this, 0, intent, 0);
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
// Start every 30 seconds
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 30*1000, pintent);
If you are unclear, go through this tutorial

Write a IntentService. Inside it, just start a new Thread. In the Thread.run(), put an infinite while loop to call your notification code and Thread.sleep(15 * 60 * 1000)....

If you want to schedule your tasks with the specified interval don't use flags AlarmManager.RTC and AlarmManager.RTC_WAKEUP with method alarm.setRepeating(...). Because in this case alarm will be bounded to the device's real time clock. So changing the system time may cause alarm to misbehave. You must use flags AlarmManager.ELAPSED_REALTIME or AlarmManager.ELAPSED_REALTIME_WAKEUP. In this case SystemClock.elapsedRealtime() will serve as a basis for scheduling an alarm.
The code will look like:
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + checkIntervalMillis, checkIntervalMillis, pendingIntent);
If you want your long running task to be executed when device in the sleep mode I recommend to use WakefulIntentService library by CommonsWare: https://github.com/commonsguy/cwac-wakeful

Related

The AlarmManager is unreliable, are there improvements or alternatives?

I need a widget to be updated frequently using a set value, like every 1-5 seconds.
I found out that for this an AlarmManager should be used.
I tested the AlarmManager's setExact() method and found out, that its minimum time is exactly 5 seconds.
I also noticed that the interval can have huge delays.
I tested this with a set interval of 5 seconds.
My test showed for the setExact() method following values: 5s, 5s, 40s, 41s, 19s, 5s, 5s, ...
Using the setRepeating() method showed even worse value: 17s, 39s, 7s, 75s, 60s, ... Apparently the AlarmManager also does not trigger at all when used on a Samsung Device, which is the Device I am planning to use the widget on.
Is there an alternative to using an AlarmManager?
Can the AlarmManager somehow become more reliable?
I need the update rate to be constant, without delays like this.
final AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent notifyIntent = new Intent(this, AlarmReceiver.class);
final PendingIntent notifyPendingIntent = PendingIntent.getBroadcast
(this, NOTIFICATION_ID, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
long triggerTime = SystemClock.elapsedRealtime()
+ 3000;
long repeatInterval = 1000;
alarmManager.setExact(AlarmManager.RTC_WAKEUP,
triggerTime, notifyPendingIntent);
Besides the AlarmManager I have checked out the JobScheduler and Worker, but both seem to underlie a 15 minute (!) minimum interval.
Using a simple Thread seems to be working however. I just have to find out how to make it run reliably then...
If you know other solutions please let me know!

AlarmManager inconsistent behavior (alarm firing multiple times, or not at all)

I have a button that sets an Alarm using the AlarmManager.setRepeating and another button that removes it, every time an alarm is set the requestCode in the PendingIntent is iterated as to not confuse it with one that has already been set and canceled (the app will have multiple alarms set at the same time in the future). when i set the alarm (setRepeating) sometimes it works as intended sometimes it will fire off twice really quickly than at the time it was intended to go off 2-3 minutes later (i'm setting the alarm 3-5 minutes in the future for my test).
Also note: I have the device plugged in and the screen is set to stay a wake, during testing the app is usually always in foreground, sometimes i put it to background or rotate the screen (usually by mistake).
I have tried setExact() but i don't mind if its off by 0-5 minutes but i do need it to go off and not repeat.
i have played around with the initial time setting it to have started the day before at the hour and minute i want it to go off, same thing with ten days back and a hundred (just to see what would happen) similar results.
I am using Joda DateTime to get the milliseconds of the alarm time for the setRepeating method, and using AlarmManager.INTERVAL_DAY to set the intervals for the next alarm (my alarms need to go off every 24 hours)
requestCode is a constant int that i increment and track during testing.
context i get from getBaseContext() in the activity
My code to set the alarm:
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
intent.putExtra(ALARMS_INDEX_KEY,requestCode);
PendingIntent sender = PendingIntent.getBroadcast(context, requestCode, intent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);//After after 5 seconds
addAlarmIndex(context, requestCode);
//test: DateTime.now().minusDays(10).withTimeAtStartOfDay()
DateTime set_for = DateTime.now().withTimeAtStartOfDay().withHourOfDay(14).
withMinuteOfHour(34).withSecondOfMinute(0).
withMillisOfSecond(0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, set_for.getMillis(), AlarmManager.INTERVAL_DAY , sender);
My code to cancel the alarm:
Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(context, requestCode, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(sender);
My code in AlarmManagerBroadcastReceiver extends BroadcastReceiver
#Override
public void onReceive(Context context, Intent intent) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "test_alarm:");
wl.acquire();
int alarm_index = -1;
if(intent.hasExtra(ALARMS_INDEX_KEY)){
alarm_index = intent.getIntExtra(ALARMS_INDEX_KEY,-1);
}
Log.i("medic_debug_timertest","Alarm !!!, fired #: "+DateTime.now().toString("YYYY/MM/dd # HH:mm:ss") + " alarm_index: " + requestCode);
wl.release();
}
What i'm expecting is the alarm gets set before the time it is meant to go off, than the alarm going off at the time it was set to go off at (withing several minutes of that time)
what happens is sometimes it dose not go off at all (perhaps I set the alarm to go off to close to when i am setting it) this may not be a problem but other times it goes off shortly after i set it and it will go off twice within 0-1 seconds apart that 1-2 minutes later it will go off again at the correct time it was set to go off at.
from what i observed so far it is always one of the three scenarios:
goes off at the correct time.
goes off not at all.
goes off three times, twice right away (1-2 minutes before the scheduled time) and than a third time at the correct time.
What am i doing wrong? how can I get the alarm to go off once at approximately the right time
UPDATE:
ok so... first of all I changed changed the line that sets up the timer from:
DateTime set_for = DateTime.now().minusDays(10).withTimeAtStartOfDay().withHourOfDay(14).
withMinuteOfHour(34).withSecondOfMinute(0).
withMillisOfSecond(0);
to
DateTime set_for = DateTime.now().plusMinutes(5).withSecondOfMinute(0).withMillisOfSecond(0);
so that it will go off exactly 5 minutes from when i set it and i can make multiple test without re running the app. I was concerned I was setting the alarm to close to when i set it up.
Something to remember is the AlarmManager bunches the alarms up and fires them at the same time if they are close together (with the setRepeating method not setExact), this is to save batteries and no wake the phone up every minute or two.
i did the test with the above code and it started to work more normally. set up 4 alarms 1 minute apart, 3 of them went off at the same tome when the 3rd one was supposed to go off (which is correct behavior because they get bunched up to one to save batteries) and the last one went off very late 3-5 minutes after it was supposed to (which is fine, no problem).
So perhaps the problem is after i canceled an alarm and start a new one the AlarmManager is getting confused (when i was setting the alarm before, to close to when i set it up) and trying to group the canceled one and the one that is supposed to go off and making the not canceled one go off twice? sounds odd but perhaps Alarm are somewhat bugged???
Ok Im not 100% sure why the alarm was triggering the same one three times, but when i give more time for the alarm to run (say 5 minutes in the future apposed to 3 minutes), giving it more time seemed to solve lot of problems. feeling a little silly now for not giving it more time in the first place but every test takes 5 minutes to run, lots of waiting, which is annoying but works better now.
in the post:
setRepeating() of AlarmManager repeats after 1 minute no matter what the time is set (5 seconds in this case, API 18+)
it is mentioned:
"As of I think Android 5.1 (API version 22) there is a minimum period of 1 minute for repeating alarms, and alarms cannot be set less than 5 seconds in the future"
I was definitely within that time(or not within that time rather, more that 5 seconds), but increasing the alarm set further in the future fixed my issue.
UPDATE: during testing I set my initial timer time to several days in the past, I have noticed that if it passed the interval even if the timer was not set than it will trigger a notification as several times as it passed those intervals from the time it was set from even if the alarm was not actually set at or before that time, so that's why i was getting those extra notifications, i assume there is a limit of 2 alarms (with the same requestCode) that it can go off like this.

how to set an alarm 5 mins before an event?

I m creating a APP that works like a virtual time card: The user enter what time he enters at work, what time he goes out for lunch and what time he comes back at work again. Then he presses a button and he can see what time he can go out. Of course this is useful for whom, like me, have a flexible working hour.
The APP works. Now I'd like to add a new feature. Let's say I can exit my office at 5 PM, I'd like that my APP at 16:55 sent me a notification, an alarm. Something that reminds me that I can go out. How can do it ?
In my mind I have these steps:
I put in a variable the time I can go out from work
I check the current time and if it's five mins before the point 1 sends a notification
But, the program has to do this check everytime or once each minute at least. And I really don't know how to do it..
Can anyone helpe me out with an idea?
Ivano
Edit according to the rules and my new updates -
sorry my delay but I had to study what you sent me because I am a super rookie in Java... And i am really struggling trying to learn new things... Anyway let's get to the point. I tried to use the AlarmManager but It's not doing what I would like.
I added this code at the top of my MainActivity class:
AlarmManager alarmMgr = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, OnAlarmReceive.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),1*60*1000, pendingIntent);
What I get is that each 60 seconds the APP reloads itself, calls the MainActivity class and reloads the values the user entered previously into the DB. Therefore there is no way to enter a new value without see!!
What Id like is: The app stays in background "forever" and wakes itself up only when realises that in 5 minutes the user can leave the office.
I already wrote the part of the code where the program checks the current time and ask itself "does it lack 5 mins before the user can leave the office ? " and if the answer is yes, a text message appears and a sound is played. This is the part of the code :
NotificationCompat.Builder n = new NotificationCompat.Builder(this)
.setContentTitle("Arrivato nuovo messaggio!!")
.setContentText("Autore: Nicola Rossi")
.setSmallIcon(android.R.drawable.ic_dialog_info)
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setSound(sound);
So, the program works.. but has a minor glitch, where it only sends the notification out when I open the app 5-minutes before the end of my shift. If I open the app at any other time, it will not send out the notification. I want this notification to be sent out regardless of the time I open the app.
How can I fix it?
What you are looking for is called an alarm manager. This is a service outside your app you can use to notify the user. This service is called upon using pending intents.
https://developer.android.com/reference/android/app/AlarmManager.html

Timer BroadcastReceiver - onReceive at 2pm or after 44min?

I would like to register a BroadcastReceiver in the Android manifest, or in code if necessary, that would send a broadcast to my application based on time.
e.g. i would like my onReceive to be called time-dependently by the Android OS
at say a regular interval
or at a given time of day
or once after a specific amount of time has lapsed (say after 44 minutes from some call in my application)
How might that be possible without leaving my app running in the background all the time ?
See AlarmManager and android.intent.action.TIME_TICK

i want to make my android app run in the background 24/7 unless closed by the user..what do i do..?

i want my app to run in the background as it has to get the time every second..and do some task when the user sets a time and wants the app to do some task at that time..!!
Have you considered using the AlarmManager?
Android provides an AlarmManager
service that will let you specify an
Intent to send at a designated time.
This intent is typically used to start
an application at a preset time.
(Note: If you want to send a
notification to a sleeping or running
application, use Handler instead.)
If you do something every second, it us unlikely the user's device will reach the 24 part without being plugged in to power.
Android apparently already contains a scheduling service so you don't need to create your own.
Does this article help. Don't forget to follow up the links provided in that article.
I agree with every single person in this thread! AlarmManagers are your best friends when it comes to executing services at a certain interval. They are very easy to set up too, here's a very simple example of a repeating alarm:
//Get the alarm service
AlarmManager alarm = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
//Create the intents to launch the service again
Intent new_intent = new Intent(<The intent to set off>);
PendingIntent p_intent = PendingIntent.getBroadcast(this, 0, new_intent, 0);
//Create a repeating alarm
alarm.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, <Time in milliseconds to set off first alarm>, <How long between each alarm in milliseconds>, p_intent);
Note that I'm using an inexact alarm to set of the alarm so it doesn't try to interrupt any other important services. It is possible to use an exact alarm but if your execution isn't really that important I highly suggest inexact alarms. You can find a lot more info below:
http://developer.android.com/reference/android/app/AlarmManager.html

Categories