Android: How to stop repeating alarm without unsetting the alarm itself - android

I have an Android app where I need to trigger reminders everyday at the same time. The alarm must repeat every 5 minutes if ignored. If the user declares he read the reminder, by clicking an OK button, the alarm must stop repeating, until it is triggered the day after.
So, I want the alarm to stop repeating after the user's confirmation, and I read that with AlarmManager I should use the cancel() method. But I don't want to delete the alarm for future days, I just want it to stop repeating until next trigger.
In other words, I don't want the cancel() method to unset the alarm for the future days. Is it the default behavior of the cancel() method or do I have to cancel the alarm and then re-set it every time?
This is my code for setting the alarm:
public class AlarmSettingManager
{
private static Context context;
// Constructor
public AlarmSettingManager(Context c)
{
context = c;
}
private static class PrescriptionAlarmSetter extends AsyncTask<String, Void, Boolean>
{
SharedPrefManager sharedPrefManager = SharedPrefManager.getInstance(context);
#Override
protected Boolean doInBackground(String... strings)
{
// Get the list of prescriptions from SharedPreferences
if(!sharedPrefManager.getPrescrizioneList().equals(""))
{
try
{
JSONArray responseJsonArray = new JSONArray(sharedPrefManager.getPrescrizioneList());
int currentID = Constants.PRESCRIZIONE_ALARM_ID;
for(int j=0; j<responseJsonArray.length(); j++)
{
JSONObject singlePrescription = responseJsonArray.getJSONObject(j);
Prescrizione prescrizione = new Prescrizione
(
singlePrescription.getInt("id_prescrizione"),
singlePrescription.getInt("id_medico"),
singlePrescription.getInt("id_farmaco"),
singlePrescription.getInt("numero_pasticche"),
singlePrescription.getInt("totale_compresse"),
singlePrescription.getString("nome"),
singlePrescription.getString("ora_assunzione"),
singlePrescription.getString("posologia"),
singlePrescription.getString("suggerimenti")
);
// Start setting the alarm for current prescription
Intent alarmIntent = new Intent(context, AlarmBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast
(
context.getApplicationContext(),
currentID,
alarmIntent,
PendingIntent.FLAG_CANCEL_CURRENT
);
// put the RequestCode ID as extra in order to identify which alarm is triggered
alarmIntent.putExtra("id", currentID);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
// Specify the time to trigger the alarm
calendar.set(Calendar.HOUR_OF_DAY, prescrizione.getIntHour());
calendar.set(Calendar.MINUTE, prescrizione.getIntMinutes());
calendar.set(Calendar.SECOND, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// Set the time interval (in milliseconds) to repeat the alarm if the previous one was ignored
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 300000L, pendingIntent);
currentID++;
}
}
catch(JSONException e)
{
e.printStackTrace();
}
}
return false;
}
#Override
protected void onPostExecute(Boolean b)
{
super.onPostExecute(b);
}
}
public boolean setAlarms()
{
AlarmSettingManager.PrescriptionAlarmSetter prescriptionAlarmSetter = new AlarmSettingManager.PrescriptionAlarmSetter();
prescriptionAlarmSetter.execute();
return true;
}
}
And this is the piece of code I'm going to adapt in order to cancel the alarm repeating:
Intent alarmIntent = new Intent(context, AlarmBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast
(
context.getApplicationContext(),
currentID,
alarmIntent,
0
);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
Thanks.

At the time of cancelling alarm schedule a new alarm for the next day.

The intention of the "cancel" option is to remove the alarm.
Your application should add a new alarm just as the original was setup.
You can find a nice example of implementing a full alarm in Android at the following link, including how to re-add it on device reboot.
Repeat Alarm Example In Android Using AlarmManager

Related

Android AlarmManager send Broadcast not on time

I use AlarmManager to set two action on time,
First action set on 10:00:00, and second action set on 10:15:00.
I can get two action broadcast,
and get first action broadcast on 10:00:03 (is OK),
but get second action broadcast on 10:29:15,14 minutes late!
How let AlarmManager can send broadcast on time ??
Set AlarmManager code:
#Override
public void onCreate() {
setSchedule();
}
private void setSchedule(){
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar offCal = Calendar.getInstance();
offCal.set(Calendar.HOUR_OF_DAY, 10);
offCal.set(Calendar.MINUTE, 15);
offCal.set(Calendar.SECOND, 00);
Intent offIntent = new Intent(this, AlarmReceiver.class);
offIntent.setAction(AlarmReceiver.ALUM_SCREEN_OFF);
PendingIntent offPending = PendingIntent.getBroadcast(this, 1,
offIntent, PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC, offCal.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, offPending);
Intent onIntent = new Intent(this, AlarmReceiver.class);
onIntent.setAction(AlarmReceiver.ALUM_SCREEN_ON);
Calendar onCal = Calendar.getInstance();
onCal.set(Calendar.HOUR_OF_DAY, 10);
onCal.set(Calendar.MINUTE, 00);
onCal.set(Calendar.SECOND, 00);
PendingIntent onPending = PendingIntent.getBroadcast(this, 2,
onIntent, PendingIntent.FLAG_UPDATE_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, onCal.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, onPending);
}
Receiver code:
public class AlarmReceiver extends BroadcastReceiver {
public static final String ALUM_SCREEN_ON = "screenOn";
public static final String ALUM_SCREEN_OFF = "screenOff";
private static final String TAG = "AlarmReceiver";
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.d(TAG, "get braodcast action:"+intent.getAction());
}
Hi you are using setRepeating method which wont give alarm at exact time.Alarm manager will strongly discourage other apps apart from system apps to trigger alarm accurately for the better battery optimization.so if u want to trigger alarm at a particular time means you can use setExact() method This also wont give you complete gaurantee but it will give you the most accuracy one .While setting multiple alarms at a single time make sure you are giving different ids in `
PendingIntent onPending = PendingIntent.getBroadcast(this, 2,
onIntent, PendingIntent.FLAG_UPDATE_CURRENT);
here you gave 2 as id and it should be different for different alarms.
Since KitKat the set and setRepeating APIs are not exact. If you absolutely need the alarm to run at a specific time, use setExact. Consider using setWindow instead if the alarm time is not critical.
There is no setExactRepeating, so if you need that, you need to use setExact and them re-arm your alarm. But unless your are doing time critical stuff, that's not recommended.

Android repeating Alarm Manager sets off immediately

TL;DR - AlarmManager .setRepeating is starting immediately instead of the desired future time.. (for example 5 minutes from now)
So basically I am starting an alarm manager and i'm giving it the time left to operate and for some reason it is firing instantly.. the user is choosing a time from a time picker, and I set this time for the next alarm.
code below:
-this method get's the time left until the alarm, this is used as the triggerInMillis for the alarmManager.
/** calculate the time left until the alarm with calendar */
private static long getTimeFromCalendar(final int hourOfDay, final int minute) {
Date dat = new Date();//initializes to now
Calendar cal_alarm = Calendar.getInstance();
Calendar cal_now = Calendar.getInstance();
cal_now.setTime(dat);
cal_alarm.setTime(dat);
cal_alarm.set(Calendar.HOUR_OF_DAY,hourOfDay);
cal_alarm.set(Calendar.MINUTE, minute);
cal_alarm.set(Calendar.SECOND,0);
if(cal_alarm.before(cal_now)){
cal_alarm.add(Calendar.DATE,1);
}
long calAlarm = cal_alarm.getTimeInMillis();
long calNow = cal_now.getTimeInMillis();
long timeLeft = (calAlarm - calNow);
return timeLeft;
}
then I call the -startAlarm- method :
private static void startAlarm(final Enums typeToStart) {
final PendingIntent pendingIntent = GBAlarms.createPendingIntent(OnAlarmReceiver.class, Constants.typeEnum, typeToStart);
final long timeToAlarm = Utils.getTimeToAlarm(typeToStart);
long repeatTime = Constants._24hours;
GBAlarms.createRepeatingAlarm(timeToAlarm, repeatTime, pendingIntent);
}
and finally, my -GBAlarms.class- where i create my alarms and pending intents.
public class GBAlarms {
/** Define our AlarmManager */
private static AlarmManager mgr = (AlarmManager) BaseApplication.getAppContext().getSystemService(Context.ALARM_SERVICE);
/** Create a new PendingIntent */
public static PendingIntent createPendingIntent(final Class destination, #Nullable final String extra, Enums.TeaType type) {
Intent i = new Intent(BaseApplication.getAppContext(), destination);
if (extra != null && type != null) { i.putExtra(extra, type); }
PendingIntent pi = PendingIntent.getBroadcast(BaseApplication.getAppContext(), type.getValue() , i, 0);
return pi;
}
/** Create a new repeating Alarm */
public static void createRepeatingAlarm(final long time, final long repeatTime, final PendingIntent pi) {
mgr.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, repeatTime, pi);
}
}
I don't understand, for some reason the alarm pops right when I set it in the -createRepeatingAlarm- method, and I debugged of course, the time parameter looks legit.. if I set it to 3 minutes, 10 minutes, it puts that time left in the trigger..
can anyone spot my mistake? maybe I'm missing something?
thanks a lot for any help.
You are creating a "pending" alarm,
a alarm that repeats after a specific interval.
The trick is to cancel the current alarm in the moment you are starting.
Look at the code below: You have to call the method getBroadcast with the
flag PendingIntent.CANCEL_CURRENT
AlarmManager alarmMgr;
PendingIntent pendingIntent;
public void startAlarmManager()
{
Intent dialogIntent = new Intent(getBaseContext(), AlarmBroadcastReceiver.class);
alarmMgr = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
pendingIntent = PendingIntent.getBroadcast(this, 0, dialogIntent,PendingIntent.FLAG_CANCEL_CURRENT);
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis(), 10000, pendingIntent);
}
}
why are you using ELAPSED_TIME?
please try using RTC_WAKEUP and switch
long timeLeft = (calAlarm - calNow);
with just calAlarm
you don’t need to mills left, you need the mills that you want it to pop.

Create alarm service in android for multiple times

in my task application, i want to create alarm service for multiple items. Here is the code i followed to create service. Lets assume, if there are more than 5 items present in list. then we will sent alarm service for 5 different times.
What if the user comes and edits the time?, how to update the system and make sure it triggers at new instance?. What if the user delete the task, how to quickly removes the registered alram for the deleted task?
What about uninstalling the app?, how to clear all the entries?, what if the system re-boots?
This is the code i'm following to register the task in alram services
Calendar Calendar_Object = Calendar.getInstance();
Calendar_Object.set(Calendar.MONTH, 8);
Calendar_Object.set(Calendar.YEAR, 2012);
Calendar_Object.set(Calendar.DAY_OF_MONTH, 6);
Calendar_Object.set(Calendar.HOUR_OF_DAY, 14);
Calendar_Object.set(Calendar.MINUTE, 25);
Calendar_Object.set(Calendar.SECOND, 0);
Step 2:
We need to create an alarm which help us to invoke the BroadCastReceiver on our specified time.
// MyView is my current Activity, and AlarmReceiver is the BoradCastReceiver
Intent myIntent = new Intent(MyView.this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
MyView.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
/*
The following sets the Alarm in the specific time by getting the long value of the alarm date time which is in calendar object by calling the getTimeInMillis(). Since Alarm supports only long value , we're using this method.
*/
alarmManager.set(AlarmManager.RTC, Calendar_Object.getTimeInMillis(),
pendingIntent);
Use this method to set Alarm :
public static void startAlarm(Context context, int alarm_code, String time) {
String[] arrTime = time.split(":");
intent = new Intent(context, AlarmReceiver.class);
intent.putExtra("CODE", alarm_code);
PendingIntent mAlarmSender = PendingIntent.getBroadcast(context,
alarm_code, intent, 0);
Calendar cal_alarm = Calendar.getInstance();
cal_alarm.setTimeZone(TimeZone.getDefault());
cal_alarm.set(Calendar.HOUR_OF_DAY, Integer.parseInt(arrTime[0]));
cal_alarm.set(Calendar.MINUTE, Integer.parseInt(arrTime[1]));
AlarmManager am = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, cal_alarm.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, mAlarmSender);
}
Here,"int alarm_code" is your unique code for particular item.
And for update alarm first cancel the existing alarm and set new alarm for new time.For that use this method :
public static void cancelAlarm(Context context, int alarm_code) {
AlarmManager am = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra("CODE", alarm_code);
am.cancel(PendingIntent.getBroadcast(context, alarm_code, intent, 0));
}
Here,"int alarm_code" will be your unique code which you have used to set alarm.So that alarm with particular alarm_id will be cancel.You can also delete alarm with this method.
Same way you can clear all the alarms passing alarm_code to the given function.
You have to register receiver for system reboot and in onReceive of register you have to set all alarms again.
Hope this will help you.

android alarmmanager + task schedule

I need help. Im new to android coding.
I have made task list, which I want to do specific things at time written in task.
Here is my task item
private long id;
private int mon;
private int tues;
private int wednes;
private int thurs;
private int fri;
private int satur;
private int sun;
private int profile;
Where I have days (monday,tuesday etc) which holds amount of minutes (for 10:00 its 600).
Following some tutorials I have alarm reciever
public class AlarmReciever extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
try {
Bundle bundle = intent.getExtras();
String message = bundle.getString("alarm_message");
Intent newIntent = new Intent(context, AlarmActivity.class);
newIntent.putExtra("profile", message);
newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(newIntent);
} catch (Exception e) {
Toast.makeText(context, "There was an error somewhere, but we still received an alarm", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
Its still unedited...
And then there is code which calls to make new tasks in alarm manager
// get a Calendar object with current time
Calendar cal = Calendar.getInstance();
// add 5 minutes to the calendar object
cal.add(Calendar.MINUTE, 5);
Intent intent = new Intent(ctx, AlarmReceiver.class);
intent.putExtra("alarm_message", "O'Doyle Rules!");
// In reality, you would want to have a static variable for the request code instead of 192837
PendingIntent sender = PendingIntent.getBroadcast(this, 192837, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Get the AlarmManager service
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
I dont understand how to specify in calendar, that I need new task repeating (for example) every monday at 10:00, and that when this happens, it calls new function, giving it "profile" variable to work with.
private void setProfile(Integer profile)
{
// Doing things with profile
}
take a look at the following code:
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent2 = new Intent(context, SampleAlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent2, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
// Set the alarm's trigger time to item hour
calendar.set(Calendar.HOUR_OF_DAY, NuevoItemActivity.hora.getCurrentHour());
calendar.set(Calendar.MINUTE, NuevoItemActivity.hora.getCurrentMinute());
// Set the alarm to fire , according to the device's clock, and to repeat once a day.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, (PendingIntent) alarmIntent);
As you can see in last line, you are able to indicate AlarmManager.INTERVAL_DAY to repeat the PendingIntent.

Cancel an AlarmManager pendingIntent in another pendingintent

I want cancel AlarmManager which define a service,in this service might start a new AlarmManger or cancel alarm that defined before.And I know the params pendingintent in alarmManager.cancel(PendingIntent),must be the same.compare with filterEquals(Intent other)
but It still not work.cancel failed.
here is my code
public class GetRoundStroe {
private Store[] stores;
private Context mContext;
public GetRoundStroe(Context mContext) {
this.mContext = mContext;
}
public Store[] getStores() {
if (ComCommand.haveInternet(mContext)) {
start_am_normal();
} else {
start_am_silence();
}
return stores;
}
public Store[] start_am_silence() {
long firstTime = SystemClock.elapsedRealtime();
AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
if (AlarmHolder.mAlarmNormal != null) {
am.cancel(AlarmHolder.mAlarmNormal);
}
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime, TestSwitch.getInstance().getSilence_time(), AlarmHolder.mAlarmSilence);
return null;
}
public Store[] start_am_normal() {
long firstTime = SystemClock.elapsedRealtime();
AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
if (AlarmHolder.mAlarmSilence != null) {
MyLog.e(GetRoundStroe.class,"AlarmHolder.mAlarmSilence"+AlarmHolder.mAlarmSilence+"");
am.cancel(AlarmHolder.mAlarmSilence);
}
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
firstTime, TestSwitch.getInstance().getNormal_time(), AlarmHolder.mAlarmNormal);
return null;
}
private static final class AlarmHolder {
static final PendingIntent mAlarmSilence = PendingIntent.getService(ApplicationContext.getInstance(),
0,
new Intent(ApplicationContext.getInstance(), GetRoundSilenceService.class),
0);
static final PendingIntent mAlarmNormal = PendingIntent.getService(ApplicationContext.getInstance(),
0, new
Intent(ApplicationContext.getInstance(), GetRoundNormalService.class),
0);
}
}
GetRoundSilenceService and GerRoundNormalService invoke start_am_normal() or start_am_silence; Anyone could help me? thanks
myIntent = new Intent(SetActivity.this, AlarmActivity.class);
pendingIntent = PendingIntent.getActivity(CellManageAddShowActivity.this,
id, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
pendingIntent.cancel();
alarmManager.cancel(pendingIntent);
These lines of code surely can help you remove/cancel the pending intent and alarm.
The main thing that you will need is:
Create pending intent with the same id and appropriate intent FLAG.
Cancel that pending intent.
Cancel the alarm using alarm manager.
#MKJParekh answer is correct, however I would like to add more information so that we all know what will work and what will not.
Lets say on activityA you create and set the AlarmManager to open activityC in 30 seconds, then on some other activity which can be any, we want to cancel that AlarmManager. Thus, we would do the following;
in activityA we create and set the AlarmManager;
//activityA
Intent myIntentA = new Intent(actvityA.this, activityB.class)
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent myPendingIntent = PendingIntent.getActivity(activityA.this, 0, myIntentA, PendingIntent.FLAG_ONE_SHOT);
//Calendar with the time we want to fire the Alarm
Calendar calendar = Calendar.getInstance(); // Get Current Time
calendar.add(Calendar.SECOND,30); //Fire Alarm in 30 seconds from Now.
((AlarmManager)getSystemService(ALARM_SERVICE)).setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), myPendingIntent);
in Another Activity some time later we want to cancel such AlarmManager created in activityA which we have no access to. Lets call this current activity activityZ;
//activityZ
Intent myIntentZ = new Intent(activityZ.this, activityB.class);
PendingIntent pendingIntentZ = PendingIntent.getActivity(activityZ.this, 0, myIntentZ, PendingIntent.FLAG_ONE_SHOT);
((AlarmManager)getSystemService(ALARM_SERVICE)).cancel(pendingIntentZ);
Some important points,
The context we provide in activityA in new Intent(context) and getActivity(context) are the same, however they do not have to match the activity from where we are canceling the AlarmManager, in this case activityZ has another context.
The class we want to open with the AlarmManager has to be the same in both activities new Intent (context, activityB.class), the requestCode which is an int must be the same, I used 0 for this example. Finally the flag has to be the same in both activities PendingIntent.FLAG_ONE_SHOT.
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); was used because PendingIntent.getActivity requires it if we are starting an activity outside of a context of an existing activity.

Categories

Resources