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

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.

Related

Can't stop the ringing alarm from another activity

I am new to android ,Here I am practicing my first app (Alarm App).
I have an issue in my app that I can't stop the alarm once a alarm is triggered it's keep on ringing can't get stopped.
In my app I have 2 activities and a AlarmReceiver .
From the AlarmActivity.java I have set the alarm ,when the specific time is reached the Alarmreceiver.java will get triggered and the alarm started to ring and showing a wakeup screen .
From the WakeUpScreen.java I have a stop button by using that I need to stop the current ringing alarm .
I don't have any issues in logcat too.
AlarmActivity.java
public void stopAlarm(Context context) {
Intent intent = new Intent(context,AlarmReceiver.class);
intent.setAction("ALARM_OFF");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, mAlarmId, intent,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
}
I have this AlarmStop() function in my AlarmActivity.java which will get hit when I press the stop button in wakeupscreen.java
When I am try to debug the stop process the debugger moved all the lines in the stopAlarm() function but the Intent is not worked that's why the AlarmReceiver.java file is not get called ,I mean,The debugger moved all the lines in the aboved method but the AlarmReceiver.java is not get called
I tried lot of ways to solve this but I missed something that I can't figured it out.
Can anyone help me to stop the triggered alarm and it's ringing sound .
Your architecture is broken. You don't use a BroadcastReceiver for persistent processing. A BroadcastReceiver has a very short lifecycle, you use it to trigger other things.
You've created a MediaPlayer instance in your BroadcastReceiver and are trying to control that in onReceive(). This is wrong. You should use a Service to manage and maintain the state of your MediaPlayer.
See if you can find some HOWTO guides on the Internet for how to build such an application.

Do i need to use broadcast with alarm manager?

i'm creating an alarm application, and this is the method to run the alarm :
public void startAlarm(int minuteToStart)
{
Toast.makeText(context, "Alarm Start in " + formatTime(minuteToStart), Toast.LENGTH_SHORT).show();
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MINUTE, minuteToStart);
Intent intent = new Intent(context, AlarmActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, idPendingIntent, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
}
And it run this activity after given specific time:
public class AlarmActivity extends Activity {
......
}
It works, but i see people are using BroadcastReceiver, am i doing it wrong? should i use BroadcastReceiver too? I've been searching about BroadcastReceiver but i don't get what difference it will make with my application.
Thanks.
In the general case, A--C's answer would be correct.
However, you are using RTC_WAKEUP as the alarm type. The only guarantee that we have with _WAKEUP alarms is if we use a BroadcastReceiver, then Android will ensure that the device will stay awake long enough for us to execute onReceive(). Any other type of PendingIntent -- activity or service -- has no guarantee, and it is very possible for the device to fall back asleep before the startActivity() or startService() actually occurs.
You can use AlarmManager with whatever PendingIntent is capable of (Activity, service, Receiver), though, it is usually used with Receivers - taks executing in the future usually are small and don't need an Activity to run in since the user doesn't need something popping up.
A Receiver isn't an Activity, so it does not have a UI and it has a processing time limit of about 10 seconds, so make sure to be quick. If you require a UI to be shown at a specific time, stick with an Activity, but usually this isn't the case unless it's something like an Alarm Clock app that the user has to see). If you have something like a small behind the scenes operation, go for a Receiver. The Receiver's onReceive() gets a Context passed to it so it can do anything a Context can.
Just keep in mind you will have to change the PendingIntent.getActivity() call to whatever else you decide to use if it's not going to be an Activity.
So it all depends on what you want to do.
You don't have to use a BroadcastReceiver. It's just generally frowned upon (in most cases) to steal focus and launch an Activity from the background without user interaction. There are certainly valid use cases though. If you intend to launch an Activity immediately anyway, doing that directly instead of via BroadcastReceiver is perfectly valid.

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 .

How to handle an alarm triggered each day in 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.

Categories

Resources