I have a table in my database where each row describes a schedule. For example:
ID | CODE | DAY | TIME
___________________________________
1 1 Mon 8
2 27 Wed 15
In other words, every Monday at 8 am, the function corresponding to code 1 is called. Every Wednesday at 3 pm, the function corresponding to code 27 is called, etc.
What's the right way to call ALL these tasks at their proper times in Android? I've seen both AlarmManager and JobScheduler but I don't know which one is more appropriate to use for something like this.
I don't need the times to be super precise (having the events trigger +/- a few seconds or even minutes from the designated times is not a huge deal), but I do need them to trigger whenever possible.
Alarm Manager will be more appropriate as one way or the other what you are trying to do maps upon the requirement of creating alarms.
If you just need to trigger event with schedule without network or charge check, Alarm Manager is lightweight and working solution.
You can try this library for quick Alarm Manager implementation.
https://android-arsenal.com/details/1/4755
Use AlarmManager with setExactAndAllowWhileIdle
Be aware that on marshmallow and later, task scheduled with AlarmManager might be delayed due to Doze. The only way to get exact timing is to use setAlarmClock which might display an alarm clock icon in the status bar on some system.
Related
The game I am working on is a missile-oriented GPS-based combat game on Android. The app checks every 15 minutes to see if the user is under attack by any other players, and if so, sends them a notification that they are under attack. Currently, because of the minimum 15 minute interval, the app sends these notifications either too late or not at all. What I need to do is alter this so that somehow, some way, the app checks the "under attack" status of the user more often than 15 minutes. Every minute or every 30 seconds would be ideal.
here is the doWork() method which starts the notification check:
{
if(!MainActivity.GetRunning())
{
Utilities.DebugLog(context, "AlertService", "Main activity not running. Firing notification service handler.");
NotificationServiceHandler handler = new NotificationServiceHandler(context);
handler.Start();
}
return Result.SUCCESS;
}
WorkManager is not a suitable tool for what you wish to do. You will need to use a foreground service and your own in-process timing engine (e.g., ScheduledExecutorService). That will not work for very long before Doze mode and other power-saving measures take effect, but hopefully your games are only an hour or so long.
Hej theBiscuit,
instead of using WorkManager, you could set up an AlarmManager to wake up the app and check for attacks.
If you want to do it while the app is running, a CountDownTimer could help for short periods of time.
Is there any way to schedule a notification to appear at a specific time?
I am developing an app that reminds a user to change their bandage every 6/12 hours and I wish to send a notification to the user 6/12 hours after they confirm that they have applied the bandage.
Is there any way to do this? I have tried to implement the alarmManager Class however every example I have found uses a specific time of the day as opposed to 6/12 hours after an event.
I have an app which checks whether to show a notification every 24 hours. You can change it to whatever interval you would like.
with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) {
// Create a PendingIntent which AlarmManager would raise.
// You should have a BroadcastReceiver to receive the intent and send a push notification.
setInexactRepeating(
AlarmManager.RTC_WAKEUP,
startAt.toEpochSecond() * 1000,
intervalInMillis,
pendingIntent
)
}
startAt -> Epoch when your alarm should start working (preferably in future). If this is in past, it will immediately boradcast the intent.
intervalInMillis -> Interval in milliseconds. For your case this should be 6 hours.
If your app requires different alarms (notifications) at 6 and 12 hours, I would still go with 6 hours or even 3 hours as the interval. When the broadcast is received, you should check if the app is supposed to send a notification or not. If not, don't do anything.
Read more about Scheduling repeating alarms.
Note: AlarmManager is affected by doze mode and you need to reset all your alarms after the phone restarts. Clubbing this with WorkManager would be ideal. But this should get you started.
Schedule tasks with WorkManager
https://developer.android.com/topic/libraries/architecture/workmanager/
Previously firebase-jobdispatcher-android was working fine now google introduced new WorkManager for scheduling task.
Here is a simple implementaion
http://thetechnocafe.com/how-to-use-workmanager-in-android/
I have a problem using setExactAndAllowOnIdle. In my AlarmReceiver class I just show simple notification that shows when alarm was triggered and set another, same alarm but hour after.(currentTimeMillis + 60*60*1000). When my phone is in use application works fine, alarms come exactly on time. But when I let it work for few alarms without waking device up, they start to trigger with few minutes delays, or sometimes even exactly on time I wake up my phone.
You probably mean setExactAndAllowWhileIdle().
You didn't tell on which OS are You testing it but probably it's because of Doze Mode.
NOTICE:
Neither setAndAllowWhileIdle() nor setExactAndAllowWhileIdle() can
fire alarms more than once per 9 minutes, per app.
So You can't use this method to set every alarm what probably You doing.
For more information You can go here:
https://developer.android.com/training/monitoring-device-state/doze-standby.html
In my application I want to trigger a recurring alarm at about a specified time to check for some conditions and notify the user if necessary.
I'm using the following code to schedule the alarm:
Calendar cal = ...;
...
mAlarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, mAlarmIntent);
I now noticed (because I accidentially had the wrong day in cal) that the alarm would be triggered right away if cal was some date/time in the past.
So let's say it is 2016-09-20 18:00:00 and I schedule the alarm for 2016-09-20 17:00:00. I'd get a notification right away (or a couple of seconds after scheduling the alarm). This does not happen if I schedule the alarm for a future time like 2016-09-20 18:15:00.
So my questions are:
Will Android always catch up on the missed alarm?
The alarm is scheduled to repreat daily. Will it then repeat at 17:00:00 tomorrow or will it be at 18:00:00, because that was when the alarm was last triggered?
Will Android always catch up on the missed alarm?
if the set time is in past then android trigger alarm as soon as possible. check the docs
The alarm is scheduled to repreat daily. Will it then repeat at
17:00:00 tomorrow or will it be at 18:00:00, because that was when the
alarm was last triggered?
Next time it will be triggered on time
Additional Info : if the use clear app data or forced close your app from application manager then alarm won't trigger until user open your app again plus reboot can also cause this.
I searched but didn't really find something. Just some examples for running AM every 20 seconds after hit a button etc.
I want that on the first start of my app an AM is started which runs every day at 3 pm and checks some things. It should be possible that the AM is running everyday even if the app doesn't start for 2-3 days.
Can anyone help me?
Step #1: Create a Calendar object that represents 3pm tomorrow. Make sure that it is tomorrow, as if it is after 3pm today, just saying "3pm" will give you a time in the past.
Step #2: Use that with AlarmManager. Use setRepeating() for Android 4.3 and below. For Android 4.4 and above, doing something at a precise time is frowned upon, and so you will probably wind up calling setExact() to get control once, then in that code call setExact() again to schedule the next event.
Step #3: If you want to wake up the device when these events occur, use RTC_WAKEUP for the alarm type, and tie it to either a WakefulBroadcastReceiver or a regular BroadcastReceiver that uses my WakefulIntentService.