Does anyone know how to do snooze function and where I am going wrong?
My default snooze time is 5 minutes. It worked fine until restart the
application and then does not work again.
If I clear the cache and data its works again.
public void onClick(View view) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
int iSnoozeLeft = settings.getInt(PuzzleAlarm.SNOOZE_LEFT, 1);
if (iSnoozeLeft != 0) {
Intent activate = new Intent(AlarmNotification.this, AlarmReceiver.class);
PendingIntent alarmIntent = PendingIntent.getBroadcast(AlarmNotification.this, 0, activate, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
int iMinutes = Preferences.getSnooze(settings, AlarmNotification.this);
Calendar calendar = Calendar.getInstance();
calendar.roll(Calendar.MINUTE, iMinutes);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), alarmIntent);
SharedPreferences.Editor editor = settings.edit();
editor.putInt(PuzzleAlarm.SNOOZE_LEFT, iSnoozeLeft - 1); // disabling
// Commit the edits!
editor.commit();
}`
PendingIntent.getBroadcast(AlarmNotification.this, 0, activate, 0);
Make sure you aren't using "0" for your other alarm ID. In other case your "snooze" code will overwrite that previous alarm.
Related
I was using setRepeating() function to schedule events in my Application. According to Android documentation setRepeating() is not exact from API level 19+.In the app, when it is time to alarm (every day at 23:59) broadcast receiver is called. However, this broadcast receiver is being called too early(ex: sometimes it is being called right after I set the alarm although there are more than 10 hours until 23:00)
Here is my code:
set Alarm function:
public void setEmaResetAlarm(Context context) {
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManagerMorning = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
intentResetNight = new Intent(context, EMAAlarmRcvr.class);
intentResetNight.putExtra("ema_reset_night", true); //time to reset EMA to 0
intentResetMorning = new Intent(context, EMAAlarmRcvr.class);
intentResetMorning.putExtra("ema_reset_morning", true); //time to reset EMA to 0
intentRemove = new Intent(context, EmaDismissReceiver.class);
intentRemove.putExtra("ema_pop_up_remove", true); // time to remove EMA pop up
pendingIntentResetNight = PendingIntent.getBroadcast(context, 10, intentResetNight, PendingIntent.FLAG_UPDATE_CURRENT);
pendingIntentResetMorning = PendingIntent.getBroadcast(context, 8, intentResetMorning, PendingIntent.FLAG_UPDATE_CURRENT);
pendingIntentRemove = PendingIntent.getBroadcast(context, 11, intentRemove, PendingIntent.FLAG_UPDATE_CURRENT);
if (alarmManager == null || alarmManagerMorning == null)
return;
emaTimeSubscription = context.getSharedPreferences("SubscriptionCheck", Context.MODE_PRIVATE);
int hour1 = Integer.parseInt(emaTimeSubscription.getString("hours1", null));
int hour2 = Integer.parseInt(emaTimeSubscription.getString("hours2", null));
int hour3 = Integer.parseInt(emaTimeSubscription.getString("hours3", null));
Calendar firingCallReset = Calendar.getInstance();
firingCallReset.set(Calendar.HOUR_OF_DAY, 23); // at 11:59pm
firingCallReset.set(Calendar.MINUTE, 59); // Particular minute
firingCallReset.set(Calendar.SECOND, 0); // particular second
firingCallReset.set(Calendar.MILLISECOND, 0); // particular second
//alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, firingCallReset.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntentResetNight);
Calendar firingCalResetMorning = Calendar.getInstance();
firingCalResetMorning.set(Calendar.HOUR_OF_DAY, 9); // at 9:30am
firingCalResetMorning.set(Calendar.MINUTE, 30); // Particular minute
firingCalResetMorning.set(Calendar.SECOND, 0); // particular second
firingCalResetMorning.set(Calendar.MILLISECOND, 0); // particular second
//alarmManagerMorning.setRepeating(AlarmManager.RTC_WAKEUP, firingCalResetMorning.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntentResetMorning);
//remove EMA pop up
Calendar firingCalRemove11 = Calendar.getInstance();
firingCalRemove11.set(Calendar.HOUR_OF_DAY, hour1 + 1); // at 11:01am
firingCalRemove11.set(Calendar.MINUTE, 1); // Particular minute
firingCalRemove11.set(Calendar.SECOND, 0); // particular second
firingCalRemove11.set(Calendar.MILLISECOND, 0); // particular second
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, firingCalRemove11.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntentRemove);
Calendar firingCalRemove15 = Calendar.getInstance();
firingCalRemove15.set(Calendar.HOUR_OF_DAY, hour2 + 1); // at 3:01pm
firingCalRemove15.set(Calendar.MINUTE, 1); // Particular minute
firingCalRemove15.set(Calendar.SECOND, 0); // particular second
firingCalRemove15.set(Calendar.MILLISECOND, 0); // particular second
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, firingCalRemove15.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntentRemove);
Calendar firingCalRemove19 = Calendar.getInstance();
firingCalRemove19.set(Calendar.HOUR_OF_DAY, hour3 + 1); // at 7:01pm
firingCalRemove19.set(Calendar.MINUTE, 1); // Particular minute
firingCalRemove19.set(Calendar.SECOND, 0); // particular second
firingCalRemove19.set(Calendar.MILLISECOND, 0); // particular second
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, firingCalRemove19.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntentRemove);
}
BroadcastReceiver to be called:
public class EMAAlarmRcvr extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
SharedPreferences loginPrefs = context.getSharedPreferences("UserLogin", MODE_PRIVATE);
SharedPreferences configPrefs = context.getSharedPreferences("Rewards", MODE_PRIVATE);
//For resetting ema prefr (11:59 PM ) and (9:30 AM )
if (intent.getBooleanExtra("ema_reset_night", false) || intent.getBooleanExtra("ema_reset_morning", false)) {
SharedPreferences.Editor ema_editor = configPrefs.edit();
SharedPreferences.Editor hrm_editor = configPrefs.edit();
Log.e("TAG", "onReceive: TaskManager" );
hrm_editor.putBoolean("hrm_completed", false);
hrm_editor.apply();
ema_editor.putBoolean("ema1_answered", false);
ema_editor.putBoolean("ema2_answered", false);
ema_editor.putBoolean("ema3_answered", false);
ema_editor.putInt("ema_answered_count", 0);
ema_editor.apply();
SharedPreferences.Editor loginEditor = loginPrefs.edit();
loginEditor.putBoolean("ema_btn_make_visible", false);
loginEditor.apply();
}
}
}
Before setting a new alarm you should cancel any previous alarms as:
alarmManager.cancel(pendingIntent);
Also, use same pending intent that you use to create a new alarm to cancel old set one because is used as unique identifier, so:
// cancel old alarm
alarmManager.cancel(pendingIntentRemove);
// then create new one
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, firingCalRemove11.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntentRemove);
You get called at random times because is created a new alarm
So far I've been using AlarmManager and BroadcastReceiver like this:
private void setUpStreakResetAlarm() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.add(Calendar.DAY_OF_MONTH, 1);
Intent intent = new Intent(getApplicationContext(), DailyCounterCheckReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 100, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
}
And in my DailyCounterCheckReceiver class:
#Override
public void onReceive(Context context, Intent intent) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
int counterOld = sharedPreferences.getInt(GlobalUtilities.SHARED_PFC_STREAK_COUNTER_OLD_KEY, 0);
int counterToday = sharedPreferences.getInt(GlobalUtilities.SHARED_PFC_STREAK_COUNTER_KEY, 0);
SharedPreferences.Editor editor = sharedPreferences.edit();
// If user has increased counter on this day, increase the old check for tomorrow
if (counterToday > counterOld) {
counterOld = counterToday;
editor.putInt(GlobalUtilities.SHARED_PFC_STREAK_COUNTER_OLD_KEY, counterOld);
editor.putBoolean("increasedOld", true);
editor.putBoolean("reset", false);
}
// etc.....
But with new Android versions, background tasks like that just get killed and it's very unreliable.
So what can I use instead? Work Manager, Foreground Service, something else?
And don't I still need AlarmManager to trigger them?
My use case is extremely simple, so I don't think I need some super complex solution, but there are so many options out there. What is better for my simple case?
Edit:
Angel's comment would solve my reset problem, but I also do the same for triggering notifications at certain times:
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putLong("lastTimeOfNotifTrigger", System.currentTimeMillis());
editor.apply();
repository = new NotificationRepository(context);
repository.startGetNextNotificationAsync(this);
}
How could I solve that in the easiest way?
You could use alarmManager.setExact to schedule the alarms (so that your receiver is called exactly at the time you want even if the phone is sleeping or in Doze mode). Once your receiver is called you can schedule the next. Remember to also add receivers detecting BOOT and PACKAGE_CHANGED so that you can re-schedule the alarms in case the phone is rebooted or the app updated.
You could also use Work Manager as you said to schedule a job, if you don't need it to be run at an exact time.
Your code shouldn't have any other issue running in newer versions of Android if you are not trying to launch an Activity from that receiver (you can't launch an activity anymore from the background).
I am trying to change one key of the shared preferences file at the end of the day. So here is what I managed to find on the internet:
boolean alarmUp = (PendingIntent.getBroadcast(this, 0,
new Intent(this, AlarmResetFoodAdded.class),
PendingIntent.FLAG_NO_CREATE) != null);
if (!alarmUp) {
setAlarm();
}
Function setAlarm():
private void setAlarm() {
alarmMgr = (AlarmManager)this.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(this, AlarmResetFoodAdded.class);
alarmIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
}
AlarmResetFoodAdded.java:
#Override
public void onReceive(Context context, Intent intent)
{
pref = context.getSharedPreferences(AppControl.PREF, Activity.MODE_PRIVATE);
prefEditor = pref.edit();
prefEditor.putInt("foodAdded", 0);
prefEditor.commit();
}
I am testing this using the device simulator with API 28. I tried to set the time to about 13:59. Then I'd wait until about 14:01 because it is inExactRepeating, but the key foodAdded in the preferences file stay the same, even when I reopen the app.
I'm pretty sure the alarm is up because when I debug alarmUp, the value is false the first time, then when I reopen it, it is true.
I think you should use prefEditor.apply(); instead of prefEditor.commit(); in your onReceive method.
I'm building an Android pedometer app that sends data to a SQLite database at 30 minute intervals using AlarmManager; if the phone is off when the transfer is supposed to occur, it will do the transfer immediately when the phone is switched back on.
(30 minutes is for testing - the actual interval will be 1 week).
I was told alarms wouldn't persist unless I used "intent.action.BOOT_COMPLETED" in the manifest, so I put that as a filter for my Alarm.java class.
My code to set the alarm (in MainActivity.java) is as follows:
public void insertData(View view) {
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
long time= System.currentTimeMillis();
Date d = new Date(time);
editor.putLong("alarmtime", time); //the next ring time for the alarm is put in SharedPreferences
editor.apply();
Intent intent = new Intent(this, Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
this,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC, time, AlarmManager.INTERVAL_DAY, pendingIntent);
Toast.makeText(MainActivity.this, "Alarm Set", Toast.LENGTH_LONG).show();
}
The code in the Alarm.java class (which extends BroadcastReceiver) is as follows:
Context context; //plus other declared variables
#Override
public void onReceive(Context context, Intent intent) {
this.context = context;
preferences = context.getSharedPreferences("MyPreferences", context.MODE_PRIVATE);
editor = preferences.edit();
long startedtime = preferences.getLong("alarmtime", 0); //get the next ring time
Date nextRingTime = new Date(startedtime);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
String action = intent.getAction();
//sometimes the onReceive() is called by the phone turning on
if (action != null && action.equals(Intent.ACTION_BOOT_COMPLETED)) {
//if phone turned on again before the alarm, just re-create the alarm for the same time, don't transfer data
Date currenttime = new Date(System.currentTimeMillis());
if ((currenttime.compareTo(nextRingTime) < 0)) {
Intent newintent = new Intent(context, Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
0,
newintent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC, startedtime, AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
return;
}
else if ((currenttime.compareTo(nextRingTime) > 0)) {
//if the phone was off when the alarm was supposed to make the transfer, set the alarm to the next intended ring time and insert data to db immediately
Calendar d = Calendar.getInstance();
d.setTime(nextRingTime);
d.add(Calendar.MINUTE, 30);
long newtime = d.getTimeInMillis();
Intent newintent = new Intent(context, Alarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
context,
0,
newintent,
PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.RTC, newtime, AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
}
}
myDb = new DatabaseHelper(context);
// code for inserting data into database
//finally, update next intended ring time in SharedPreferences now that this particular transfer is done:
Calendar c = Calendar.getInstance();
c.setTime(nextRingTime);
c.add(Calendar.MINUTE, 30);
Log.v("insertdone, alarrm now", c.getTime().toString());
long nexttime = c.getTimeInMillis();
editor.putLong("alarmtime", nextime);
editor.apply();
}
Unfortunately, if the phone is off at the time of a scheduled alarm, when I turn it on afterwards, it calls onReceive() TWICE, meaning it inserts data twice.
How can this be stopped?
A solution would maybe be to use RTC_WAKEUP, but I really don't want to do that unless as an absolute last resort.
N.B. I have a separate bootBroadcastReceiver class that uses "intent.action.BOOT_COMPLETED" to restart a pedometer service, and am wondering whether having 2 different things started by the boot is causing problems...
I'm using alarm manager to call for api. it is called in a activity onCreate. I want it to call an alarm at start of the app then alarms every three hours.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY,1);
AlarmManager alarmManager1 = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent myIntent1 = new Intent(LobbyActivity.this,WeatherBroadCastReceiverCurrent.class);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(this,0,myIntent1,0);
alarmManager1.setInexactRepeating(AlarmManager.RTC,calendar.getTimeInMillis(),AlarmManager.INTERVAL_HOUR+
AlarmManager.INTERVAL_HOUR+AlarmManager.INTERVAL_HOUR/*(1000*60*60*3)*/,pendingIntent1);
That activity is then finished and proceeds to another activity when a button is clicked. My problem is-if the activity is recreated it calls an alarm even if it is not the time. Can I set an alarm on a non activity class so it will not be recalled when the activity is recreated?? if so how? Tia
try to run by removing calendar.set(Calendar.HOUR_OF_DAY,1); and run, it will call alarm at start of app
To simply get over this, you need to create a flag and make it true so that the activity can check if the Alarm has been set before, it is has, then it will move forward without setting it.
Use of SharedPreferences is ideal for this.
This is one of my snippets, edit it according to your need.
SharedPreferences prefs;
SharedPreferences.Editor ed;
prefs = PreferenceManager.getDefaultSharedPreferences(this);
ed = prefs.edit();
boolean isOpeningForTheFirstTime = prefs.getBoolean("firstTime", true);
if(!isOpeningForTheFirstTime) {
Intent i = new Intent(this, StartScreen.class);
startActivity(i);
finish();
}
And the AlarmManager can be simplified by removing a few things.
public void setAlarm(){
//To get the current time
long alertTime = new GregorianCalendar().getTimeInMillis();
//Interval of a minute
int timeInterval = 60000;
//Intent which you want to start
Intent alertIntent = new Intent(this, ClassName.class);
//Declaring the alarmManager
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
//Setting the alarmmanager up.
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alertTime, timeInterval, PendingIntent.getBroadcast(this, 1, alertIntent, PendingIntent.FLAG_UPDATE_CURRENT));
}