So I am having an issue with AlarmManager. I am trying to run some code every 2 minutes, which works okay while the phone is awake, but not when the device goes to sleep - during sleep, the intervals are perfectly 5 minutes apart.
Since my desired interval is 2 minutes, this is roughly 250% off my target interval, which for my specific application is not acceptable.
I am aware of the changes in API 19, and have followed suggestions to re-schedule the alarm using setExact() within my BroadcastReceiver. Code is below:
The code used to trigger BroadcastReceiver:
Intent intent = new Intent(this, AlarmReceiver.class);
final PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
mAlarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 3000, pendingIntent);
And this code is in my BroadcastReceiver which re-schedules the alarm:
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "AlarmService Triggered.", Toast.LENGTH_SHORT).show();
Log.d(this.getClass().getSimpleName(), "Service triggered");
Intent newIntent = new Intent(context, this.getClass());
mPendingIntent = PendingIntent.getBroadcast(context, 0, newIntent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 120000, mPendingIntent);
}
Does anyone have suggestions as to how I could fix this? It is very frustrating that AlarmManager is totally ignoring my wish to have an alarm fire at an exact time. Is there any alternative that will allow me to schedule code at 2 minute intervals like I want?
DEVICE: Samsung Galaxy S6, OS 5.1.1
As #Francesc suggested, it ended up being the Samsung device. Tried it on another phone, now it works flawlessly.
Let this be a lesson to you - don't buy Samsung, they do weird stuff, lol.
Replace ELAPSED_REALTIME_WAKEUP with RTC_WAKEUP.
This is how I schedule alarms:
mTargetTime = System.currentTimeMillis() + timeout * 1000L;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, mTargetTime, mPendingIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, mTargetTime, mPendingIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, mTargetTime, mPendingIntent);
}
Related
I'd like to repeat an alarm every 20 minutes.
So I tried:
manifest:
<receiver android:name=".AlarmReceiver" />
AlarmReceiver.class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent intent2 = new Intent(context, MainActivity.class);
showNotification(context, "text", "text", intent2);
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(context, notification);
r.play();
}
#TargetApi(Build.VERSION_CODES.N)
public void showNotification(Context context, String title, String body, Intent intent) {
...
}
}
and in my main activity:
AlarmManager alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
Calendar time = Calendar.getInstance();
time.setTimeInMillis(System.currentTimeMillis());
time.add(Calendar.SECOND, 1200);
alarmMgr.set(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(), pendingIntent);
It is working only the first time. I'd like to keep it repeating even when the app is not opening, any ideas?
Starting with KitKat (API 19), alarms are all inexact, meaning the system will batch alarms around similar times together. If you need exact timing, there are different APIs to call. Further complicating things, starting with Marshmallow, Android introduced the concept of Doze, which further restricts the when/how things can wake up the device. You can still use exact alarms, but need to use the API which allows it during idle (Doze) time: setAndAllowWhileIdle(). Bear in mind that when your alarm fires, you could be in a Doze window and your app will be restricted on what kinds of operations it can perform.
Try below for Repeating alarm on every 20 minutes interval
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, time.getTimeInMillis(),1000 * 60 * 20, pendingIntent);
Try to use android worker manager since it is working with doze mode as well. https://developer.android.com/reference/androidx/work/PeriodicWorkRequest#min_periodic_interval_millis
https://developer.android.com/reference/androidx/work/PeriodicWorkRequest
Since the introduction Doze Mode and App StandBy managing alarms have changed. The problem I'm facing is my alarm manager fires correctly on KitKat, Lolipop and Marshmellow devices but above API 23 it does not fire unless the app is in foreground or background. But if the app is killed, the alarms are stopped.
Checked out Google Keep Application on my Android 7, turns out it does the same.
But Google Calendar fires regardless of whether the app is killed or not.
Done some reading and found out setExactAndAllowWhileIdle method on the alarm manager ensures to break the doze mode and trigger your alarm.
But it does not work, is there anything I'm missing here?
Here's my code:
Intent alertIntent = new Intent(this, NotificationPublisher.class);
alertIntent.putExtra("Hello", "Meal Time");
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
int id = (int) System.currentTimeMillis();
if (Build.VERSION.SDK_INT < 23) {
if (Build.VERSION.SDK_INT >= 19) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, delay, PendingIntent.getBroadcast(this, id, alertIntent, PendingIntent.FLAG_UPDATE_CURRENT));
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, delay, PendingIntent.getBroadcast(this, id, alertIntent, PendingIntent.FLAG_UPDATE_CURRENT));
}
} else {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, delay, PendingIntent.getBroadcast(this, id, alertIntent, PendingIntent.FLAG_UPDATE_CURRENT));
}
Broadcast Receiver:
public class NotificationPublisher extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("Hello");
Log.d("Called", "Meal Time");
}
Manifest:
<uses-permission android:name="android.permission.WAKE_LOCK" />
<receiver android:name=".NotificationPublisher" />
Because of battery optimisation it is not working,i turned off the battery optimisation of particular app, it is working fine in oneplus 3.
You wanna white-list your app from battery optimisation programatically, check this link stackoverflow.com/a/42651399/3752079
Try with adding below line for your alertIntent
myIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,myIntent, 0);
I want an Alarmmanager to fire first time after 2 Seconds and then every 10 Sec.
It doesn't fire the first time exactly 2 seconds later. Something between 5 and 10 sec later. And it doesn't repeat at all.
Here is my Code:
Alarmmanager:
Intent intent = new Intent(this, BackgroundService.class);
final PendingIntent pendingintent = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0);
final AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis() + 2 * 1000, 10 * 1000, pendingintent);
Manifest:
<receiver android:process=":remote" android:name=".BackgroundService"/>
BackgroundService.java:
public class BackgroundService extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("BackgroundService", "BackgroundService onReceive");
}
}
Got it:
The IDE says: The 3rd value will be forced up to 60000 (1 Min) to save battery. But I never waited so long, so it looked like it doesn't even repeates.
Snap is here
am.setRepeating(AlarmManager.RTC_WAKEUP, **cal_alarm.getTimeInMillis()**, 1000*60*5 , pendingIntent);
I think you are using System.currentTimeMillis() because of which you are having that issue. Try to get the time from you code for which you have set the Alarm. The third parameter in the above code is the repeating time. You can set it to 10 sec.
this heslp me
if (android.os.Build.VERSION.SDK_INT >= 19) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
} else {
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
I have this method which should schedule alarms but when the time arrives it doesn't start the pendingintent ??
public void setAlarm(String name, long time) {
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent dialog = new Intent(this, SubActivity.class);
dialog.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pi = PendingIntent.getActivity(this, 0, dialog, 0);
if (Build.VERSION.SDK_INT >= 19) {
if (System.currentTimeMillis() < time) {
am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, pi);
}else{
time+=(AlarmManager.INTERVAL_DAY*7);
am.setExact(AlarmManager.RTC_WAKEUP, time, pi);
}
} else {
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, AlarmManager.INTERVAL_DAY * 7, pi);
}
}
The problem is you are using a PendingIntent for an Activity, which will not necessarily keep the device awake long enough for the Activity to get started. You'll have to use a PendingIntent for a BroadcastReceiver which leverages a wake lock to keep the device awake until your app code can run. WakefulBrodcastReceiver is a good choice, or you can roll your own as needed. See this article for an explanation and sample of how to use alarms to wake the device: http://po.st/7UpipA
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.
}