How to handle an alarm triggered each day in android - android

I want to set an alarm in my application which will be triggered each day. According to the doc, I have to set a one-time alarm, and in the BroadcastReceiver which will receive the alarm signal, reset the alarm for the day after.
Is that correct ?
My BroadcastReceiver handles well the wakelock and launch a service which releases this wakelock. Everything works fine here.
However I have problems. In my application there is a checkbox which is checked when alarm is up. To know if my alarm is up, I use the following condition :
Intent intent = new Intent( context, AlarmReceiver.class );
boolean alarmUp = (
PendingIntent.getBroadcast( context, 0, intent, PendingIntent.FLAG_NO_CREATE) != null)
But this doesn't seem to work very well, is that a good way to know if an alarm is up ?
Thanks in advance

For the first part of your question, you could just use a repeating alarm, or schedule a new alarm whenever one fires like you are doing. Either way works.
You may also want to setup a broadcast receiver that receives ACTION_BOOT_COMPLETED so you can reschedule your alarms when the phone reboots.
As for checking if the alarm exists, the PendingIntent with FLAG_NO_CREATE is exactly how you would do that.

Related

Android development: [HOW TO] intercept daily alarm and dismiss programmatically

I'd like to implement an Activity that launches a Service able to intercept/receive the daily scheduled clock alarm and dismiss it programmatically when an event is fired (i.e. a recognize speech event).
In practice I have:
public class MyReceiver extends BroadcastReceiver {
...
}
registered on a ALARM_ALERT_ACTION (com.android.deskclock.ALARM_ALERT) [i've read that this works only with the system clock app]
Now when the Alarm ring MyReceiver.onReceive(...) method is called correctly but i can't dismiss (neither snooze) the alarm by code.
I've founded many examples use AlarmManager instance with .cancel(PendingIntent) method call but probably this works only when the alarm is scheduled by a custom Intent.
I've tried also getting all running processes and kill the com.android.deskclock process but is a not working way.
So, to summarize, I've scheduled a daily alarm with the system android clock app and i'd like to have a service that intercept com.android.deskclock.ALARM_ALERT action/event and dismiss it by code.
Thanks in advance to all.
I've founded how to do...check the code below:
AlarmManager alrm = (AlarmManager)getApplicationContext().getSystemService(ALARM_SERVICE);
Intent intent = new Intent(MyService.ALARM_DISMISS_ACTION);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, intent, 0);
alrm.set(AlarmManager.RTC_WAKEUP, 1000, pi);
In practice with these instructions I launch a "dismiss" alert event and this produce a current alarm ring dismission ;)
Bye
I believe the only way to dismiss an alarm would be to either 1) intercept the alarm broadcast and redirect it to a false boolean, or 2) if the alarm app had an API to call.

Android - Alarm doesn`t fire sometimes after long period

I have a big problem with my app for several days now. I appologize if my english is not so native in advance. I implemented an AlarmManager to give the user of my app the option to start a certain service at any time of the current or the next day. So e.g. the user might choose to set the time for my service to tomorrow at 08:00 a.m. and then starts the service.
The alarm manager should now wait the calculated time from now till the chosen time (i calculated the time also manually and it is correct!) and then start the service. My problem now is that sometimes the alarmmanager is starting my service and somtimes not. It seems that if it has to wait for lets say more than 4 hours it is not working any more and my service is not called. I have set all neccessary permission otherwise it would not work at all. You can have a look at the code of the alarmmanager below:
someIntent = new Intent();
someIntent.setAction("START_SERVICE");
AlarmManager alarams ;
alarmIntent = PendingIntent.getBroadcast(MainActivity.this, 0, someIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarams = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarams.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+delay, alarmIntent);
The broadcast receiver is implemented like this (and it is registered!):
alarmReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(MainActivity.this, MyService.class);
startService(myIntent);
}
};
As I told you, if it is not working it stops before starting the service.
EDIT:
I have an idea. I read something in this thread: Android long running service with alarm manager and inner broadcast receiver
It might be, that my constructor for the intent "someIntent" only works for BroadcastReceivers declared in the manifest file. So in my case I should maybe use someIntent = new Intent("START_SERVICE") instead of someIntent = new Intent(); someIntent.setAction("START_SERVICE"). This effect is called tunneling - i will figure it out, if it works i will post my experience here. Thanks for the well explained answer on the mentioned thread! If you have any other ideas or the same experiences like me please let me know!
eMu
If the device is shutdown and start up then you will not get the alarm maanger broadcast receiver.
Implement OnBootReceiver which will receive the OnBoot completed and there you can start your pending alarms that were not fired.

Android Alarm and service trigger

Couple of question on Alarm registration and starting service on trigger.
If an alarm is set at couple of mins ahead of current time and then if phone is made switch off, will the alarm trigger on next phone switch on after the schedule time passed?
How to cancel / update pending intent in service? How to get request code in startCommand() method of service?
Will there be a multiple instances of service created if the alarm is triggered after every 10 seconds?
If "switch off" means full power down and not just "once shortly press power button to turn screen off" the answer is "no"
I think you can't get request code at all. As the documentation on getService states, the requestCode field is "currently not used". You should pass all your data with Intent (third arg of getService).
Will not. See http://developer.android.com/reference/android/content/Context.html#startService(android.content.Intent)
Every call to this method will result in a corresponding call to the target service's onStartCommand(Intent, int, int) method
Store the time of the alarm in SharedPreferences. Then register a receiver for android.intent.action.BOOT_COMPLETED (remembering to add a permission for android.permission.RECEIVE_BOOT_COMPLETED to your manifest), and then in the receiver, which will execute on startup, you can see if the alarm's in SharedPreferences, and if so you can reset it if it hasn't passed yet, or decide what to do if the time has already passed.
See problem with cancel the alarm manager pending intent
No. The service's onCreate will only be called once. Its onStart and onStartCommand will be called each time.
From my own app that I'm developing, if an alarm is set for a time when the phone is turned off, it has been executed on the next phone on/boot. That is without a receiver for BOOT_COMPLETED being present. I am unsure if this is expected behaviour or not, or whether it is consistent over phone variants.
I believe if you wish to have your alarm execute the intent at its specified time, you need to use a getBroadcast PendingIntent with a WakeLock as other variants of PendingIntent do not guarantee that phone will remain awake long-enough before it shuts down again. This is information from another post here by CommonsWare, that I will try to find and link to.
I believe you can remove the pendingintent sent to the alarm manager using, for example, a function like:
public void unregisterEvent(PendingIntent sender) { ((AlarmManager) this.getSystemService(Context.ALARM_SERVICE)).cancel(sender);
}
where the PendingIntent has been created exactly as the original intent you are trying to remove. You can update it by supplying the correct id along with a new PendingIntent when calling AlarmManager again:
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
This is what I use to create/rebuild the PendingIntent:
PendingIntent.getService(this, uniqueIndexToIntent, theIntentItself, PendingIntent.FLAG_UPDATE_CURRENT);
The flag will update the intent if it already exists, or will create a new one otherwise.
I don't think it will. However, I'd recommend having your Service call stopSelf() once it has finished doing its work, so that battery usage is minimised. No need to have it running if it has nothing to do!

AlarmManager Bug while Resetting/Cancelling Alarm on Date and Time Change

I want to send data to server at some regular interval. So, I am using AlarmManager for the same. It works fine but the problem is that when I cancel the Alarm on Date/Time change. At that time Alarm fires again before getting cancelled, so that makes my application worse as an extra data is sent to server with irregular interval.
Here is my BroadCastReceiver class with AlarmManager.
public class MyReceiver extends BroadcastReceiver{
AlarmManager mgr;
PendingIntent pi;
Intent intent;
public static boolean flag = false;
#Override
public void onReceive(final Context arg0, Intent arg1) {
if(arg1.getAction().equals("android.intent.action.TIME_SET")){
Log.d("MyReceiver", "Time set");
mgr = (AlarmManager) arg0.getSystemService(Context.ALARM_SERVICE);
intent = new Intent(arg0, TestService.class);
intent.putExtra("test", "testvalue");
pi = PendingIntent.getService(arg0, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
if(!flag){
mgr.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + 10000, 5000, pi);
flag = true;
}
else{
mgr.cancel(pi);
pi.cancel();
flag = false;
}
}
}
}
Below is the Screen Shot with Logcat output that explains that after cancelling the Alarm it fires once more time just after cancelling.
As you can see in the Logcat output black arrow shows where I changed that time to cancel the Alarm and red arrow shows that after cancelling the Alarm once again it fired just before cancelling which should not happen. So, can anyone give my idea why that is happening and what should I do to restrict Alarm getting fired again before cancelling.
NOTE:- This only happens when I tried to increase date/time say from 10:00 to 11:00, works perfect when I decrease time say 10:00 to 9:00.
Not able to see the LogCat at my end, but looking at the code, I am not sure, how is the Service which gets invoked (TestService) gets killed / stopped ? I think you would need to stop it somehow. Also, its not recommended to do long running tasks within the broadcast receiver.
Have you verified that you service stop event is occuring after the mgr.cancel(pi) is fired?
Just try with some unique code with pending intent within activity and then cancel that intent using the same code.
setting pending intent in activity
PendingIntent.getBroadcast(this, code, intent, PendingIntent.FLAG_UPDATE_CURRENT);
for stopping that broadcast receiver
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), code, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
why that is happening
First Thing is that you are using Intent Action android.intent.action.TIME_SET so It does mean that Everytime any how if the System date/time gets Changed your BroadcastReceiver will ne called Automatically.
Second you have used one static boolean flag in your Receiver class.
Now what is happening is Whenever you change your System timings the flag toggles it's state from false to true and from true to false.
That is what exactly happening in your code and logcat also shows the same that everything is working as per the code written.
So according to me there is nothing Wrong happening in the code and it's output.
what should I do to restrict Alarm getting fired again before cancelling
First thing as I think, you should not use Action TIME_SET like that to toggle flag on/off as users and developers might not remember for what they are changing time either to turn FLAG On or Off,
Better way is that,
you should handle the Service yourself by an Activity and show one ToggleButton there to manage the State of the FLAG and set and cancel the PendingIntent.
OR
And If you want to do the task of your service automatically then you just simply use the AlarmManager and set your Alarm Triggering time and Interval there only once say time is currenttime and Interval is 50000 miliseconds..
so it will obviously call the service from now onwards after every 5mins, then in your App you will only require one ToggelButton to indciate the Sync to ther server is On or Off , if user Toggle it on or off then write your AlarmManager code there in your Activity only in the toggleButtontb.setOnCheckedChangeListener(listener) , I suppose this is the better way then what you are actually implementing.
I don't understand what need to set the receiver for date change if your goal is only to send the data on server in some regular interval .
change date and time of device does not mean that your alarm wont work
at that time which you already have set before those changes .Alarmmanager work on that given duration of time which is excluding from local current date and time of device .

onAlarm fired receiver

I want to create a broadcast receiver that will get notified when an alarm is started.
For example I set the alarm to 10 am and I go to sleep, then when the alarm is fired I want to have an receiver that will be notified.
Is it possible to do this ?, is there any intent that is fired on alarm start ?
For setting alarm use Alarm-manager class. You can set alarm using pending intent and using calendar you can set the time. Check the following code, in this AlarmReceiever is broadcast receiver which receives intent from pending intent at specific time that you can set in set method as second parameter .
Intent alaram=new Intent(FirstActivity.this,AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(FirstActivity.this, 0, alaram,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(),pendingIntent);
//cal.setTimeInMillis(System.currentTimeMillis());
cant you use pendingIntent too!! just saying
It appears that there is no standart alarm used by alarm applications. So either you have to look up used alarm in your logs and use it ( this will be alarm application dependent, and
surely not portable ) or just use alarm manager and schedule your own alarm

Categories

Resources