Everyday notifications at certain time - android

I would like to achieve this:
After first turning on the application, user receives notifications, every day at 2pm, if certain condition is true. If condition is false, we are not showing a notification this day. The condition is checked at 2pm, it downloads some data from the Internet.
So far I used AlarmManager and its method setRepeating() with 24h interval. AlarmManager fires up a Service. In this Service I'm downloading the data, checking condition and if it's true - showing Notification. Since downloading can last more than 5 seconds, I've declared android:process=":background" for this Service, to run it in separate process and not block my UI.
This approach has two drawbacks:
1: If user opens application let's say at 4pm (and the condition is true), he will receive the notification immediately. From setRepeating() documentation:
If the time occurs in the past, the alarm will be triggered
immediately, with an alarm count depending on how far in the past the
trigger time is relative to the repeat interval.
I would like that user will not receive a notification this day, only the next day and so on.
2: I'm worried that my notifications will not show after user switch the phone off. From AlarmManager documentation:
Registered alarms are retained while the device is asleep (and can optionally wake the device up if they go off during that time), but will be cleared if it is turned off and rebooted.
I don't know if it's possible to make it work all the time.
If you have any ideas how to make it better, you're welcome.

1: I'm not quite sure if i understood your question, but I think all you have to do is if it already is past 2pm add a day to 2pm:
GregorianCalendar twopm = new GregorianCalendar();
twopm.set(GregorianCalendar.HOUR_OF_DAY, 14);
twopm.set(GregorianCalendar.MINUTE, 0);
twopm.set(GregorianCalendar.SECOND, 0);
twopm.set(GregorianCalendar.MILLISECOND, 0);
if(twopm.before(new GregorianCalendar())){
twopm.add(GregorianCalendar.DAY_OF_MONTH, 1);
}
alarmManager.setRepeating(type, twopm.getTimeInMillis(), 1000*60*60*24, intent);
2: You could register a BroadcastReceiver for booting and start your alarm again there. Take a look at this: Android BroadcastReceiver on startup - keep running when Activity is in Background

Related

Do you need to remove an alarm before setting new one

I have an Android alarmManager being set and a broadcastReceiver to pick it up, whenever the app triggers onResume, I am forcing a new alarm to be set.
So I'm wondering for best practices and considering good resource management, should I be removing the first alarm (if it hasn't triggered) before I reset a new alarm ?
Potentially if an alarm doesn't trigger, each time the user re-opens the app, is it creating more resource usage even if the alarm is for the same time ?
Yes you should cancel it when it is appropriate.
I suspect you will have a lot of wasted cycles otherwise. For Example,
App opens at Time T.
Schedule an alarm for T'.
Next the user opens the app again at some time, X seconds prior to T'.
You will then schedule an alarm presumable at another time T''.
However you will get an alarm firing in X secs anyways. If you ignore it, you are simply wasting battery if the phone had to wake in order to deliver the alarm.
If you create the same PendingIntent for your alarm, then the previous one will automatically be canceled when you set it again.
See AlarmManager.set(), PendingIntent.

Why is AlarmManager alarm delayed on first run?

Recently, in my timer app, running the timer for the first time causes it to fire an alarm approximately two or three seconds after it should. The strange this is, it only does this the first time I run the timer after installing the app via Android Studio. Every time after that, it runs as expected and the timer goes off after the expected time.
Here is the relevant code:
if(LOG) Log.v(TAG,"Starting the timer service: "+ TimerUtils.time2humanStr(context, mTime));
Intent intent = new Intent( this, TimerReceiver.class);
mPendingIntent = PendingIntent.getBroadcast( this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmMgr.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + mTime, mPendingIntent);
The variable mTime is set properly each time, according to the logcat output:
Starting the timer service: 5 seconds
And it works fine every time after the initial run. It was working fine before; could it be a problem with Android or Android Studio? Or am I needing to initialize something? I know I can't expect precise answers without dumping all my code here, I'm just looking for hints (speculation?) as to why this behaviour might be occurring.
Are you using API 19? Check out this note in the documentation:
Note: Beginning in API 19, the trigger time passed to this method is
treated as inexact: the alarm will not be delivered before this time,
but may be deferred and delivered some time later. The OS will use
this policy in order to "batch" alarms together across the entire
system, minimizing the number of times the device needs to "wake up"
and minimizing battery use. In general, alarms scheduled in the near
future will not be deferred as long as alarms scheduled far in the
future.
Source: AlarmManager

Creating alarm with AlarmManager for a specific period of time

Is there any way to use AlarmManager to activate an alarm for a specific period of time? I have start-time and end-time values stored in the database. I want to start an alarm at start-time that will make the device silent and alarm should end at end-time when the device volume will be normal again.
One way is set alarm at start-time & then set another alarm at end-time. But the problem is the time period may overlap that will need additional logic to be implemented if I go with 2 different alarms(one at start-time, another at end-time). Is there any procedure in Android to cope with this situation? Or implementing logic is the only way to overcome this issue?
Why not just in your Intent for the PendingIntent pass an extra like "endTime" long type for the time you want to end the alarm. (im assuming its repetitive) then in your broadcast receiver get that extra, compare to System.currentTimeMillis() and if it is less then current time cancel the alarm and exit?

Android AlarmManager Rescheduling Logic

I have an app which allows users to schedule alarms to sound at certain times, repeating at intervals of their choosing. I am using JSON to persist the alarm details, using SharedPreferences as storage.
I am using AlarmManager to schedule when my app should be notified that an alarm should sound to notify the user. I am currently using the setRepeating() method of AlarmManager, supplying the interval provided by the user. This works well, and in theory the app would never need to update the JSon which stores the next alarm time, as AlarmManager will just reschedule the next alarm time using the interval.
However, my thinking is that when the device is rebooted, I will need to supply a up to date alarm time to AlarmManager to avoid AlarmManager thinking an alarm has been missed as this is not necessarily the case.
So, what's the best way to do this?
update the JSon next alarm time when the alarm is sounded, even though this may not be necessary (setRepeating() handles this as long as there is no reboot)?
register for and listen for shutdown broadcasts and update JSon then (this raises questions - just how long will the app get to calculate and write alarm details to storage given that the phone is shutting down)?
don't update the JSon but add logic to the object which is woken by the AlarmManager to decide if the alarm just broadcast is valid and the user should be alerted?
I'm sure any of the above will work, but I can't decide which is the nicest way to do it.
This seems mostly a matter of choice. The problem you note parallels a general problem seen in Linux laptops and solved by anachrond. In my opinion, I would simply update the time and store it in SharedPreferences every time the event is received. Trying to listen for when the system shuts down might not be entirely reliable (what happens when your users -- probably drunk college students -- drop their device and the battery flies out?). Instead, I believe the best thing to do in this scenario would be to -- each time the alarm fires -- recalculate the time to send the next one, store it somewhere, and upon boot schedule appropriately.

How will my app receive an intent broadcasted by AlarmManager if the OS has closed my due to memory crunch

I am writing an alarm app, and would like to do some specific work when the alalrm is triggered. For this I use the AlarmManager.set() method and the pending intent broadcasts the intent. So far so good. But what if the OS decides to close my app which was in background due to memory crunch. Could someone help me with this.
Also if I want repeated alarms then I can use the AlarmManager.setRepeating(). Does this take into consideration the day light saving adjustment ?
The Alarm will start your application even if this isn't currently running. In order for this to happen you need to register a broadcast receiver either with the <receiver> tag in the manifest file or with the registerReceiver method. Read the documentation for details.
As for your second question, although I haven't tried it, with setRepeating you configure the interval between subsequent alarms. If for example you have your first alarm at 13:00 and use an INTERVAL_DAY interval, the alarm will fire every day at 13:00. If daylight savings take affect and 13:00 becomes 12:00, then the alarm will fire daily at 12:00. However, I suppose you need to try this out.

Categories

Resources