I have an android app where I try to set an alarm. My code inside activity:
fun setAlarm() {
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val intent = Intent(this, NotificationReceiver::class.java)
pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)
alarmManager!!.set(AlarmManager.RTC_WAKEUP, /*calculateAlarmTime()*/1, pendingIntent)
Timber.i("setAlarm executed")
}
I set this alarm, calling setAlarm method. This is my NotificationReceiver class:
public class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Timber.i("onReceive called");
}
}
Why I have only "setAlarm executed" in logcat, and not "onReceive called"? I set alarm to 1 millisecond and it should trigger immeditately. Why nothing happens?
Your second parameter is wrong. It isn't how long from now you want the alarm to occur, it's the Unix timestamp of when you want it to occur. So 1 would have happened back in 1970. You would need to, at minimum, go System.currentTimeMillis()+1. Although that may well cause race conditions, I wouldn't count on an alarm being set for less than a second in the future working.
You set the AlarmManager with RTC_WAKEUP, so you should supply the exact date and time. Instead you set the time to 1 ms, which is interpreted as 1ms after 1-1-1970, 00h00m00s.
If you want to use an relative time from setting the alarmManager you should get the current RTC time, add a few seconds and set the alarmManager with that time. As this method is inexact, allow a few seconds leeway.
See here for description RTC_WAKEUP
Related
I wrote the below code:
var alarmMgr: AlarmManager? = null
lateinit var alarmIntent: PendingIntent
class MainActivity : AppCompatActivity() {
alarmMgr = this.getSystemService(Context.ALARM_SERVICE) as AlarmManager
alarmIntent = Intent(this, MyAlarm::class.java).let { intent ->
PendingIntent.getBroadcast(this, 0, intent, 0)
}
alarmMgr?.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, AlarmManager.INTERVAL_FIFTEEN_MINUTES, alarmIntent)
}
With MyAlarm class as:
class MyAlarm : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Toast.makeText(context, "Alarm Triggered", Toast.LENGTH_SHORT).show()
}
}
My intention is to get the alert run after 15 minutes, but what is happening in real, is I'm getting the toast immediately upon the app startup, what mistake did I made, and how to fix it?
The second parameter to setExactAndAllowWhileIdle() is the time when the alarm should occur, expressed in the timebase of the first parameter.
Your first parameter is ELAPSED_REALTIME, so the second parameter needs to be SystemClock.elapsedRealtime() plus some amount, to schedule the alarm for that amount of time in the future.
Right now, you just have INTERVAL_FIFTEEN_MINUTES as the second parameter. The value of that constant happens to be 15 minutes in milliseconds. However, that will schedule the alarm to go off 15 minutes from whenever your phone last rebooted, which probably is a time in the past.
So, replace:
alarmMgr?.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME,
AlarmManager.INTERVAL_FIFTEEN_MINUTES, alarmIntent)
with:
alarmMgr?.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime()+AlarmManager.INTERVAL_FIFTEEN_MINUTES, alarmIntent)
I got a problem with the AlarmManager. When the alarm is set, if the alarm's hour has already passed the intent is started which is great. But sometimes there is a very long time (from 30 secondes to 3 minutes) before the intent is started. If anyone knows why, I'm curious to understand.
Here is my code :
public static void setAlarm()
{
Intent intent = new Intent(Application.Context, typeof(AlarmReceiver));
intent.SetAction("ExchangeGo");
PendingIntent pendingIntent = PendingIntent.GetBroadcast(Application.Context, 0, intent, PendingIntentFlags.CancelCurrent);
Calendar dayCalendar = Calendar.GetInstance(Java.Util.TimeZone.Default);
dayCalendar.Set(CalendarField.HourOfDay, 8);
dayCalendar.Set(CalendarField.Minute, 30);
dayCalendar.Set(CalendarField.Second, 0);
dayCalendar.Set(CalendarField.Millisecond, 0);
AlarmManager alarm = Application.Context.GetSystemService(Context.AlarmService).JavaCast<AlarmManager>();
alarm.Cancel(pendingIntent);
alarm.SetRepeating(AlarmType.RtcWakeup, dayCalendar.TimeInMillis, AlarmManager.IntervalDay, pendingIntent);
}
And here the intent :
[BroadcastReceiver]
public class AlarmReceiver : BroadcastReceiver
{
private String SOMEACTION = "ExchangeGo";
public override void OnReceive(Context context, Intent intent)
{
String action = intent.Action;
if (SOMEACTION.Equals(action))
{
Intent intentService = new Intent(context, typeof(ExchangeService2));
context.StartService(intentService);
}
}
}
There is no problem with manifest cause it works, just a bit too long sometimes. And the problem is not from my second intent because I put a breakPoint just before and the waiting time is before the break point.
Anyone ?
Thanks for reading me.
As setRepeating() doesn't guarantee that it will happen at precise time.
That's why you are getting delay of 30 secondes to 3 minutes.
Replace setRepeating() with setExact() refer documentation from Here
manager.setExact(AlarmManager.RTC, startTime.getTimeInMillis(), operation);
To repeat this what you can do is, to schedule this alarm again after executing your current event. So when your 1st intent gets executed schedule alarm for 2nd event using setExact() only. This will guarantee the time accuracy you are expecting
I have set alarm to get trigger after 60 seconds. but the alarm is getting triggered after 80/90 seconds (But not exactly after 60 seconds). How can i set alarm to get trigger exact at specified time?
//calling method to set alarm after 60 seconds
startAlarm(context, 1, System.currentTimeMillis()+60000);
//method defination
public static void startAlarm(Context context, int timerType, long nextScheduledTime) {
EABLog.d(TAG, " ~~~INSIDE START ALARM~~~~~ "+timerType);
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra(Constants.KEY_TIMER_TYPE, timerType);
intent.setAction(""+timerType);
PendingIntent pollPendingIntent = PendingIntent.getBroadcast(context,
timerType, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, nextScheduledTime,
pollPendingIntent);
EABLog.d(TAG, System.currentTimeMillis()+" ALARM IS SET AT "+nextScheduledTime+" TYPE :"+timerType);
}
//permission added in Android Manifest
<uses-permission android:name="android.permission.WAKE_LOCK"/>
As docs say about setExact - The alarm will be delivered as nearly as possible to the requested trigger time. So it is not as exact as you think :)
Look at public void setWindow (int type, long windowStartMillis, long windowLengthMillis, PendingIntent operation) methods 3rd parameter - windowLengthMillis The length of the requested delivery window, in milliseconds. The alarm will be delivered no later than this many milliseconds after windowStartMillis.
This might do the trick :)
I want to start a service every day from 8am to 6pm. I am using 3 alarms.
For starting alarm2 everyday at 8am.
For starting service every 1 min.
To stop alarm2.
Is it the proper way? Also I am unable to start alarm2 from alarm1.
This is code for alarm 1:
public class AlarmReceiver1 extends BroadcastReceiver {
int interval;
#Override
public void onReceive(Context context, Intent intent) {
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent in=new Intent(this,AlarmReceiver2);
PendingIntent startingIntent = PendingIntent.getBroadcast(context, 0,in, 0);
long duration = interval * 60 * 1000;
manager.setRepeating(AlarmManager.RTC_WAKEUP,timeOn.getTimeInMillis(), 86400000,startingIntent);
}
}
Far from enough code to tell if it has been set up properly. There is a good example here on how you should set up the AlarmManager. I'd recommend looking it through if there is something you've missed.
Also as you can see in the example you gotta reset the Alarms every time the phone is rebooted. If you don't the services will not run.
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.