AlarmManager setInexactRepeating not triggered repeatedly - android

I am trying to schedule alarm which will perform some task after every hour. For testing purpose, I have set the alarm to trigger after every 5 seconds but it triggers only once.
private fun register30MinSchedule() {
val alarmMgr = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val alarmIntent = Intent(this, AlarmReceiver::class.java).let { intent ->
PendingIntent.getBroadcast(applicationContext, LocationTrack_Service_ID, intent, 0)
}
alarmMgr?.setInexactRepeating(
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(),
System.currentTimeMillis() + 5000 ,
alarmIntent
)
}
AlarmReceiver is called only once. Can anyone please point me the mistake I am making?
Regards,

I was able to figure out the issue. All methods of AlarmManager requires the precise time. In my scenario, i was using the variable time for 2nd and 3rd parameter triggerTimeMillis i.e. System.currentTimeMillis() + 5000. So, the correct way of setting repeating alarm is:
val initialTime = System.currentTimeMillis()
val repeatingInterval = initialTime + 5000
alarmMgr?.setInexactRepeating(AlarmManager.RTC_WAKEUP, initialTime, repeatingInterval,alarmIntent)
This is trigger after every repeating interval. Hope this helps.

Related

I'm trying to setup an AlarmManager in my Kotlin Android app, but it triggers immediately if the alarm is in the past

I am currently trying to make an app that sends the user a message every morning. However, my alarm triggers immediately when I open my app if the alarm's trigger time is earlier than the current time.
This is my code:
This in my onCreate:
// Get AlarmManager instance
val alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
// Intent part
val intent = Intent(this, AlarmReceiver::class.java)
intent.action = "FOO_ACTION"
intent.putExtra("KEY_FOO_STRING", "Alarm triggered!")
val pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0)
val calendar: Calendar = Calendar.getInstance().apply {
timeInMillis = System.currentTimeMillis()
set(Calendar.HOUR_OF_DAY, 21)
set(Calendar.MINUTE, 42)
}
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
AlarmManager.INTERVAL_DAY,
pendingIntent
)
And my receiver just in my MainActivity:
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// Is triggered when alarm goes off, i.e. receiving a system broadcast
if (intent.action == "FOO_ACTION") {
val fooString = intent.getStringExtra("KEY_FOO_STRING")
Toast.makeText(context, fooString, Toast.LENGTH_LONG).show()
val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
vibrator.vibrate(200)
}
}
}
I found a solution to one of the major problems I was having in this question. I found a way to keep my alarm from triggering if the date I want it to trigger is in the past-
if (calendar.timeInMillis < System.currentTimeMillis()) { // checks if alarm time is earlier than system time
calendar.add(Calendar.DAY_OF_YEAR, 1) // goes to next day
}
I had another problem here initially, but I realized this was probably too many things to cram into a single StackOverflow question. I edited my question to just include this issue, and am leaving this code snippet here for people who might have this issue in the future.

How to set AlarmClock alarm from service in the background?

I want to be able to set a variable alarm from the background whenever my service is run. I am using the following code:
...
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
...
Intent i = new Intent(AlarmClock.ACTION_SET_ALARM);
i.putExtra(AlarmClock.EXTRA_SKIP_UI, true);
i.putExtra(AlarmClock.EXTRA_HOUR, 9);
i.putExtra(AlarmClock.EXTRA_MINUTES, 9);
i.putExtra(AlarmClock.EXTRA_MESSAGE, "Good Morning");
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
...
I am aware that an activity cannot be started from the background. But is there any other way or a hack to be able to accomplish what I need to do here?
Looking at Schedule Repeating Alarms documentation, you could use AlarmManager with a PendingIntent as seen below.
When you start the service, you could always set up the alarm and set the alarm to trigger straight away using the current time.
When the alarm goes off, it sends out a intent to a Broadcast Reciever (which is AlarmReceiver in the case below - just make your own). You can then do whatever you want from AlarmReceiver.
It is probably worth running through the full documentation as I found it super useful. It will only take maximum 15 minutes, is really clear and it should meet your requirement.
private var alarmMgr: AlarmManager? = null
private lateinit var alarmIntent: PendingIntent
...
alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
PendingIntent.getBroadcast(context, 0, intent, 0)
}
// Set the alarm to start at 8:30 a.m.
val calendar: Calendar = Calendar.getInstance().apply {
timeInMillis = System.currentTimeMillis()
set(Calendar.HOUR_OF_DAY, 8)
set(Calendar.MINUTE, 30)
}
// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr?.setRepeating(
AlarmManager.RTC_WAKEUP,
calendar.timeInMillis,
1000 * 60 * 20,
alarmIntent
)

Multiple Alarm fire at same time

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

AlarmManager setRepeating disregards the interval

I use this code to setup an alarm in our business application:
private void setupAlarm() {
final Context c = getApplicationContext();
final AlarmManager alarm =
(AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
final Intent i = new Intent(c, AlarmReceiver.class);
final PendingIntent sender =
PendingIntent.getBroadcast(c, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
final long startFromNow = System.currentTimeMillis()+10000;
final long timer = 5*60*1000;
alarm.setRepeating(AlarmManager.RTC_WAKEUP, startFromNow, timer, sender);
}
I cannot understand why the interval for the alarm is not respected. First alarm starts after 10 seconds (as expected), afterwards it starts every 2 minutes and a bit (122 seconds to 127 seconds), which is wrong. The interval is 5 minutes, or am I wrong?
I use this exact code in a simpler application: one activity that sets the repeating alarm and the receiver just creates a log. There it works.
What could make the AlarmManager act so different?
I have tried to:
use set() and in the alarm receiver use another set() for over 5 minutes: launch at 2 minutes
use setInexactRepeating() instead of setRepeating(): launch at 2 minutes
Any insight would be helpful. Thanks!
Immediate suggestion that comes to mind - make sure you don't set an alarm with the same intent and different value elsewhere. The intent need not be the same object, see the set methods documentation in AlarmManager.

How to Set Recurring AlarmManager to execute code daily

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.
}

Categories

Resources