AlarmManager entries - android

I set up an alarm for my PendingIntent. Now I want to show in my activity, if this alarm is set or not.
Intent service = new Intent(context, MyService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, service, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, firstStart, interval, pendingIntent);
Is there any way to check is this alarm is set?

You can't query the AlarmManager to find out if the alarm is set. You pretty much need to remember yourself. You can store something in shared preferences to indicate that you set the alarm. However, once the phone is restarted your alarms are gone, so you also need to either reschedule the alarms on a reboot OR clear your preferences to indicate the alarm is no longer set.
Unfortunately, this is one of those things that Android really lacks (a way to query the alarmManager).

Related

Android widget change alarm interval

I have created a configure activity for my widget, where the user can choose from various update frequencies.. Until now I started the alarm in the OnEnabled() method, like this:
Intent intent = new Intent(CLOCK_WIDGET_UPDATE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis(), 1000 * 60,
pendingIntent);
The settings are saved in shared preferences with a unique name (widgetId) and in this OnEnabled() method I can't retrieve the settings here because I can't get the widgetId yet.
There's an another problem, the user can change the frequency anytime, but this method is called just once, at the beginning. So I think I need to start the alarm in OnUpdate(), but I don't know how to do it, I don't want to make multiple instances of an alarm accidentally so I would like to ask for some advice.
To answer your second problem, calling setRepeating multiple times will not create multiple alarm as far as you provide same PendingIntent and same request code along with PendingIntent.FLAG_UPDATE_CURRENT flag. I would also suggest to use setInexactRepeating instead of setRepeating. So you can use the same code in OnUpdate() too with new frequency. Go through docs of FLAG_UPDATE_CURRENT and setInexactRepeating for more detials.

Android AlarmManager.set(...): notification never received when battery low

I'm attempting to use AlarmManager to schedule a delayed check in my app. (Specifically, N minutes after a user approaches a location, I want to check whether they're still there, and if so send them a notification.)
I've implemented this by checking to see whether they've entered the region in my location update receiver and, if they have, scheduling like so:
Intent geofenceIntent = new Intent(context, GeofenceReceiver.class)
// ...intent contents not important...
PendingIntent pi = PendingIntent.getBroadcast(context, 0, geofenceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar c = Calendar.getInstance();
c.add(Calendar.SECOND, getGeofenceDelaySeconds());
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pi);
Log.v("Scheduling notification check for "+c.getTime());
When the battery level is high (say, 50%), everything works like a charm. But when it's low (say, 10%), I get location updates, they schedule the alarm seemingly-successfully, but that alarm never actually triggers!
What gives? Does Android stop sending certain types of updates when it's trying to conserve power? How can I work around this (short of actually keeping my app active for the duration of the delay, which causes obvious issues with battery life)?
It turns out that this is related to the use of the real-time clock.
Although I could not find the documentation it quotes (it's not in AlarmManager), this StackOverflow answer suggests that AlarmManager.RTC_WAKEUP alarms do not trigger if the phone is in power-saving mode. AlarmManager.ELAPSED_REALTIME_WAKEUP alarms do not seem to suffer this problem, so I was able to fix the issue by switching to:
Intent geofenceIntent = new Intent(context, GeofenceReceiver.class)
// ...intent contents not important...
PendingIntent pi = PendingIntent.getBroadcast(context, 0, geofenceIntent, PendingIntent.FLAG_UPDATE_CURRENT);
long millis = SystemClock.elapsedRealtime() + 1000 * getGeofenceDelaySeconds();
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, millis, pi);

AlarmManager keeps screen of my device on

I have one problem I need to set AlarmReceiver.
I am using this code for it:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.SECOND, cal.get(Calendar.SECOND) + 5);
AlarmManager alarm = (AlarmManager)getActivity().getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(getActivity(), AlarmReceiver.class);
PendingIntent pIntent = PendingIntent.getBroadcast(getActivity(), 0, i, 0);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), 1000*5, pIntent);
So it means that this AlarmManager will call AlarmReceiver every 5 seconds, but problem is that if I don't turn my screen OFF manually, screen will stay ON and this is not what I want.
From the AlarmManager reference documents:
The parameter AlarmManager.RTC_WAKEUP, will wake up the device (in case of device sleep) to deliver the Alarm. You may use AlarmManager.RTC but that won't be wake up the device and your Alarm won't be delivered until next time device wakes up.
A better option would be to use a Service for this purpose, as they are designed to carry out the background tasks.

Delete AlarmManager Alarm ONLY for a Deleted Alarm

My app will have several alarms set simultaneously. Unfortunately, each alarm is being set with the same PendingIntent object. Here's the code I'm using to set the alarm:
//Use AlarmManager to trigger the notification/alarm.
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
//PendingIntent to launch activity when the alarm triggers.
Intent i = new Intent("com.testapp.DisplayNotification");
//Assign the reminder's primary key as the notification ID.
i.putExtra("Reminder_Name", editRemindMeTo.getText().toString());
i.putExtra("Reminder_Primary_Key", reminderPrimaryKey);
PendingIntent displayIntent = PendingIntent.getActivity(
getBaseContext(), 0, i, 0);
//Set the alarm to trigger.
alarmManager.set(AlarmManager.RTC_WAKEUP,
c.getTimeInMillis(), displayIntent);
I know that I can delete an alarm by using the following code:
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, MyPendingIntentService.class);
PendingIntent displayIntent = PendingIntent.getService(context, 0, i, 0);
alarmManager.cancel(displyIntent);
However, using this code will delete ALL my alarms (correct me if I'm wrong here). Is there a way to delete just the alarm that a user has deleted from the database? The alarm should be deleted from my app right after the user deletes an alarm entry in my app's database. I'm guessing that using different PendingIntent names would be the way to go, but I have no idea how to do this for each new alarm that a user creates. Thoughts on how to do this? Thanks!
See the same problem i faced here previously...
So the solution is to pass unique pending intent to the alarm service.. So here i how it can be done
PendingIntent pIntent = PendingIntent.getBroadcast(context, (int) alarm_id, intent, PendingIntent.FLAG_CANCEL_CURRENT);
here in the pending intent i have passed unique request id to the pending intent. Which you have to remember while cancelling the alarm.
So in my case what i have done to generate the unique id is put it in the database i have retrieved the id of the tables row and passed to the pending Intent.
So if you want to cancel the particular alarm you have to remember the same request id of the pending intent with the use of the same table entry...
I am sure it will work..
Use a different requestCode when registering each alarm. This is the second parameter of PendingIntent.getActivity/Service().
From the Android Documentation, cancel() will cancel all alarms with same pendingIntent. So the only way out is to create different pendingIntents. OR you could resort to scheduling repeating alarms as well, in this way you could use the same pendingIntents.

Best way to set multiple alarms when some are of repeating in nature in Android

I'm building a reminders application where one time, weekly, monthly reminders and we notify the user of the reminder on due date and time. Reminders can be updated any time by the user to update the reminding time or delete the reminder altogether. I have thought of two ways I can solve the particular problem.
Whenever user sets a reminder, schedule an alarm accordingly with an unique Id and update or delete it in case user updates or deletes the alarm.
Since I store the reminding time in DB, better approach would be to schedule an alarm for the nearest reminder. And have the Service which is triggered by the alarm schedule a new alarm for the next nearest reminder.
2nd approach seems clean approach but how do we tackle the case where the Service triggered by alarm gets killed by the system before it schedules a new alarm for the next reminder?
Edit
Looks like if the system kills a Service for memory, it will re-create the Service. Does it mean it is safe to rely on the Service to schedule alarm every time it is run?
Edit 2
I've realized that Android kills any alarms whenever the device is restarted. This makes approach 2 a better solution. I've implemented it for now.
The pending intent needs to be created exactly in the same way for canceling the already set alarm. You can cancel previous alarm when you set a new alarm, if you want to have a single alarm activated at some time.
For setting alarm use:
Intent myIntent = new Intent(getApplicationContext(), SessionReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, now.getTimeInMillis(), pendingIntent);
For canceling the alarm use:
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent myIntent = new Intent(getApplicationContext(), SessionReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 1, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.cancel(pendingIntent);

Categories

Resources