This problem seems a little bit odd, but if someone as encounter something like this, please help me...
I created an Alarm Scheduler, that sends an alarm to the user using AlarmManager, through this code:
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra("tk_alert_id", lastAlertId.getId()+"");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, idRandom, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, date.getTimeInMillis(), pendingIntent);
The problem is that, sometimes, I receive this alarm on my AlarmReceiver (BroadcastReceiver) at a wrong time, as you can see in the image bellow:
image, and I can't figure out what's the problem... I checked the time for date and was set as "2015-05-27 17:00:00", but it was received a little minutes earlier (around 16:57) ...
Does anyone knows what kind of problem I am encountering here?
For API levels <19 you should use AlarmManager.setRepeating() and your alarms will trigger exactly at specified time.
Api levels >=19 and above this no longer works. There was change in android so that all repeating alarms are inexact.
So if you would like to achieve exact repeating alarm use AlarmManager.setExact().
See this question for more info.
Edit
For your purpose (a one-off alarm, at a precise time) use alarmManager.setExact(....). See docs
Related
Following code works perfectly for Activity:
Intent intent = new Intent(context, MyActivity.class);
PendingIntent operation = PendingIntent.getActivity(context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmmanager.setExact(AlarmManager.RTC_WAKEUP,
startTime.getTimeInMillis(),
operation);
However, when I do the same thing for IntentService, It works only if startTime and time I set alarm are on the same day. e.g. If I set the alarm today for 5 PM, it will be executed but when I set the alarm today for 5 PM tomorrow, it will not be executed. If this was Activity then it works for both cases.
Intent intent = new Intent(context, MyService.class);
PendingIntent operation = PendingIntent.getService(context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmmanager.setExact(AlarmManager.RTC_WAKEUP,
startTime.getTimeInMillis(),
operation);
How to solve this?
The goal here I am trying to achieve is to execute IntentService every day at the exact time.
The goal here I am trying to achieve is to execute IntentService every day at the exact time.
Google has made this progressively harder from release to release. See Android AlarmManager setExact() is not exact. There could be two ways to solve this for your case:
you start an activity, which starts the service (as starting an Activity seems to work for you)
you use either setExactAnd... or setAlarmClock. setAlarmClock also triggers in the new "doze" mode, see https://stackoverflow.com/a/47049705/1587329.
Another way would be to re-think why and if you really need this... or if a JobScheduler could not fit your purpose more easily.
add replace your line with this line :
alarmmanager.setRepeating(AlarmManager.RTC_WAKEUP,
startTime.getTimeInMillis(),
operation);
it will repeat on specific interval you set in alarm manager
Replace the AlarmManager with this code:
alarmManager.setRepeating(AlarmManager.RTC,
timeMills,
AlarmManager.INTERVAL_DAY,
pendingIntent);
Worked for me.
HERE IS a DETAILED ANSWER check link in the bottom for more details.
Hope this will help. Your issue can be probably related to android versions too so do check the link for more details
app gets an instance of the AlarmManager and sets an alarm using a PendingIntent. More on usage and setting alarms is coming in the next section. The AlarmManager is the app side interface to the backing AlarmManagerService. It abstracts the details of the Binder interface, used to communicate with the system process (system_server) hosting the AlarmManagerService. These two components manage the alarm(s) the app has set and will send the PendingIntent correctly. This manager/service architecture is used throughout Android framework and is done for security and isolation purposes. The system_server process is running with privileges which normal apps do not have. If you are unfamiliar with Android’s use of permissions, see this article for more details on app processes and user IDs. These extra permissions are what allows system_server to access the underlying kernel alarm driver. The alarm driver is what manages setting alarms to wake up the device regardless of the sleep state of the SoC.
When the alarm is triggered the device is awakened (if asleep) and the AlarmManagerService is notified of an alarm expiring. It will then send the PendingIntent accordingly. This will cause the appropriate component within MyApp to be activated. If MyApp has not been started or its process is not cached, it will be started so the component can be activated.
basic usage will be as
public class MyActivity extends Activity {
...
private AlarmManager mAlarmMgr;
...
public void onCreate(Bundle savedInstance) {
...
mAlarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
...
}
...
}
let’s create a PendingIntent for our MyActivity using the component name.
Intent alarmIntent = new Intent(context, MyActivity.class);
PendingIntent pend = PendingIntent.getActivity(context,
0,
alarmIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
Now that we have our PendingIntent and the AlarmManager, we can set our alarm so our Activity is triggered when the alarm has expired. To do this, we need to figure out when we want our alarm to go off and whether it should wake up the device or just be delivered the next time the device is awakened. Remember, we have two different ways of specifying time for our alarms: elapsed time or calendar (RTC) time. So our options are ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC or RTC_WAKEUP. The _WAKEUP variants are our “aggressive” alarms where we want the device to come out of low power to call our app back. For our sample app, let’s set this up in a custom BroadcastReceiver and have it trigger our Activity about 30 seconds after the device is booted
public class MyBootReceiver extends BroadcastReceiver {
public void onReceive(Context, context, Intent intent) {
...
AlarmManager alarmMgr =
(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
long wakeTime = SystemClock.elapsedRealtime() + 30000;
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, wakeTime, pend);
}
}
Now when our device boots and the BOOT_COMPLETED broadcast is sent, our app’s process will be started and our receiver will set an alarm to trigger our Activity to be launched about 30 seconds later. Note that on Android 3.1 devices or newer, you must first manually launch your app before the BOOT_COMPLETED.
CREDIT GOES to writer of this BLOG
if you want to set the repeated alarm using SetExact you are bound to stop all other pending intents on the same time check this link for that here are many examples of how to do it! again credit goes to this writer
I want to make a repeating alarm notification that will trigger in a specific time in a day. the repeating alarm that i made is firing the alarm well but sometimes its off in its set time. for example a I set an alarm in 6:00 am but after the first trigger the following day it started at 6:15 am so i was wondering if their is a more accurate way of setting an alarm?
here is my code for my repeating alarm
Calendar calendar_dog= Calendar.getInstance();
calendar_dog.set(Calendar.HOUR_OF_DAY,7);
calendar_dog.set(Calendar.MINUTE,0);
calendar_dog.set(Calendar.SECOND,0);
Intent intent= new Intent(getApplicationContext(), notify_dog.class);
PendingIntent dog_intent=PendingIntent.getBroadcast(getApplicationContext(),100,intent,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager dog_alarm =(AlarmManager)getApplicationContext().getSystemService(ALARM_SERVICE);
dog_alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP,calendar_dog.getTimeInMillis(),AlarmManager.INTERVAL_DAY,dog_intent);
and on my reciever
NotificationManager notify_dog=(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent dog_intent= new Intent(context, HomeActivity.class);
dog_intent.setFlags(dog_intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent dog_pending=PendingIntent.getActivity(context,100,dog_intent,PendingIntent.FLAG_UPDATE_CURRENT);
Uri alarmSound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
NotificationCompat.Builder dog_build= new NotificationCompat.Builder(context).setContentIntent(dog_pending).
setSmallIcon(R.drawable.pet)
.setContentTitle("Pet Guide 101")
.setContentText("have you feed your Dog?")
.setSound(alarmSound)
.setAutoCancel(true);
notify_dog.notify(100,dog_build.build());
From Android Developers:
As described above, choosing the alarm type is often the first step in creating an alarm. A further distinction is how precise you need your alarm to be. For most apps, setInexactRepeating() is the right choice. When you use this method, Android synchronizes multiple inexact repeating alarms and fires them at the same time. This reduces the drain on the battery.
For the rare app that has rigid time requirements—for example, the alarm needs to fire precisely at 8:30 a.m., and every hour on the hour thereafter—use setRepeating(). But you should avoid using exact alarms if possible.
With setInexactRepeating(), you can't specify a custom interval the way you can with setRepeating(). You have to use one of the interval constants, such as INTERVAL_FIFTEEN_MINUTES, INTERVAL_DAY, and so on. See AlarmManager for the complete list.
So, to accomplish what you want, you need to use it like that:
dog_alarm.setRepeating(AlarmManager.RTC_WAKEUP,calendar_dog.getTimeInMillis(),AlarmManager.INTERVAL_DAY,dog_intent);
I am writing an application in which user can configure alerts/alarms. At this point, I have everything working expect the one. I am firing off an alarm using
Intent alarmIntent = new Intent(AlarmClock.ACTION_SET_ALARM);
alarmIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
alarmIntent.putExtra(AlarmClock.EXTRA_MESSAGE, "Some message!");
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, 1);
alarmIntent.putExtra(AlarmClock.EXTRA_HOUR, calendar.get(Calendar.HOUR_OF_DAY));
alarmIntent.putExtra(AlarmClock.EXTRA_MINUTES, calendar.get(Calendar.MINUTE));
alarmIntent.putExtra(AlarmClock.EXTRA_SKIP_UI, true);
context.startActivity(alarmIntent);
I want to remove this alarm once user has dismissed using the Dismiss button. I can see the alarms being still there in the alarm clock which I set using above code through my application.
Is there some way to get a cursor or something similar on the alarms being there in the alarm clock? This will help me iterate over them and remove the ones I want.
Any help would be appreciated, Thanks in advance.
As it was answered here: there is no supported API to this.
Official documentation says that
If a time of day is specified, and EXTRA_SKIP_UI is true, and the
alarm is not repeating, the implementation should remove this alarm
after it has been dismissed.
But different manufactures implement their own alarm clocks and I'm not sure if someone supporrts this.
I have tried it on JB emulator and looks like it dosen't work. Maybe, on KitKat?
Only this one is ok on JB:
If an identical alarm exists matching all parameters, the implementation
may re-use it instead of creating a new one
So, maybe, better solution is to use youre own alarm, created with AlarmManager or warn user that he has to remove Alarms by hands (to make it more obvious - not use AlarmClock.EXTRA_SKIP_UI).
call method cancel(...) from AlarmManager, using the same PendingIntent you used to set the alarm. Example:
mAlarmPendingIntent = PendingIntent.getActivity(this, requestCode, intent, flags);
this.getAlarmManager().cancel(mAlarmPendingIntent);
this refers to the Activity or the Service from which you are cancelling the alarm
I'm usign an Alarm Manager to update a widget with a Service. I've two different questions.
First question: I'm calling the service with Alarm Manager's intent. Like this:
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyService.class);
pi = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
context.startService(new Intent(context, MyService.class));
Long repeat = Long.parseLong(prefs.getString("update_preference", "600"));
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, Calendar.getInstance().getTimeInMillis(), 1000*repeat, pi);
Is it wrong?
It looks and works right. But when I have looked at working services, I can't see my service name in the list. Perhaps it's not running as a single/seperate service. Just saw application name (not as a service). I'm not sure how to seperate or does it matter?
Another question: Over long time, running application, which controls widgets update, is closed somehow (manually or by a task killer). Of course Alarm Manager gonna stop and widget's functions gonna stop too. For example button clicking.
But, Twitter solved this problem. While the widget is active, if I close the main application (Twitter) -which controls widget- than click the widget, somehow widget triggering application and it starts again well. So buttons work properly. How is that possible?
Any help would be appreciated.
You dont need to do context.startservice that what the pending intent is for, if you want the service to run right away the first time just set it to run at the current time then set the interval from the current time.
You are also setting 2 different types of repeating when you don't need to setRepeating is strict where setInexact is not and can be adjusted by the OS when it gets fired hence the inexact in it. You want one or the other not both.
Also those intervals are very small and its going to kill the battery significantly.
It should just be this
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyService.class);
pi = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
Long repeat = Long.parseLong(prefs.getString("update_preference", "600"));
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
Calendar.getInstance().getTimeInMillis(), 1000*repeat, pi);
It's good that your application/service isn't running all the time.
In fact it doesn't need/has to run all the time for updating a widget. If you schedule an Intent with AlarmManager the application will be started when the intent is fired if it has been closed.
please refer to
this for the issue i was facing....as suggested by the person who replied to my problem + what my additional research showed is that i need to use AlarmManager to solve my sleep & timertask issue...since, i have started changing the existing code to utilize PendingIntent along with AlarmManager with: Thread thr = new Thread(null, mTask, "ServiceName"); in the service...
after reading the AlarmManager documentation several times, i dont know how to reschedule a AlarmManager... im working on a Profile Switcher application, which will various run intervals (like i described in my problem thread)...
Does anyone have any suggestion?
i dont know how to reschedule a AlarmManager
Use cancel() to remove an existing alarm, and use set() or any of the other set...() methods to schedule alarms. To "reschedule" alarms, you cancel the old and create the new.
If you use the same intentString and the same request code, your alarms will be overwritten.
In your intent, you can use the following flag:
PendingIntent.FLAG_UPDATE_CURRENT
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, notification.getId(), new Intent(intentString), PendingIntent.FLAG_UPDATE_CURRENT);
long startDateTimeMillis = notification.getDateTime().toDateTime().getMillis();
MyApplication.alarmManager().setExact(AlarmManager.RTC_WAKEUP,
startDateTimeMillis,
pendingIntent);
Related to the alarm itself, you can use the methods setExact() or set() and you can search about them to check which one fits you better.