I am trying to set Android Alarm 2nd Monday and Wednesday of every month using JodaTime. I have been searching the internet for hours but I couldn't find what to put for the interval in alarmMgr.setRepeating() when I use JodaTime. Here is my code with the problem:
import java.util.Calendar;
import java.util.Locale;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
public class SampleAlarmReceiver extends WakefulBroadcastReceiver {
public static int firstOrSecond; //used for 1st, 2nd....
//Joda time calculation for 1st, 2nd... sunday, monday... of month
public static LocalDate nthWeekdayOfMonth(int dayOfWeek, int month, int year, int n) {
LocalDate start = new LocalDate(year, month, firstOrSecond);
LocalDate date = start.withDayOfWeek(dayOfWeek);
return (date.isBefore(start)) ? date.plusWeeks(n) : date.plusWeeks(n - 1);
}
// BEGIN_INCLUDE(set_alarm)
public void setAlarm(Context context) {
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, SampleAlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 700, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, 6);
calendar.set(Calendar.HOUR_OF_DAY, MainActivity.hour);
calendar.set(Calendar.MINUTE, MainActivity.minute);
//Using Joda Time
DateTime jodaCal;
jodaCal = new DateTime(calendar);
DateTime triggerMillis = new DateTime();
triggerMillis = jodaCal.isBefore(triggerMillis) ? jodaCal.plusWeeks(firstOrSecond) : jodaCal.plusWeeks(firstOrSecond - 1);
long jodaMillis = triggerMillis.getMillis();
//Set repeating alarm
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
jodaMillis, /*What to put here for interval if I want to repeat alarm 2nd Wednesday of Every Month*/, alarmIntent);
// Enable {#code SampleBootReceiver} to automatically restart the alarm when the
// device is rebooted.
ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
}
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
I tried setting AlarmManager.setRepeating() state but not getting any success,
I tried setting Alarm yesterday at 10 AM and got alarm notification for that current day only, next day I didn't get any notification at 10 AM.
Below is my code please let me know what's going wrong in my code.
Intent intent = new Intent(this, AlarmReceiver.class);
pendingIntent = PendingIntent.getBroadcast(ReminderActivity.this,0,intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
long timeInMillis = System.currentTimeMillis();
Log.i(TAG, "timeInMillis: " + timeInMillis);
Logger.addRecordToLog(ReminderActivity.this,"hours "+hour +"minutes "+minute,"triggered "+new Date());
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Log.i(TAG, "hour: " + hour);
Log.i(TAG, "minute: " + minute);
Log.i(TAG, "" + calendar.getTimeInMillis());
Logger.addRecordToLog(ReminderActivity.this,"calendar Alaram Time"+calendar.getTimeInMillis(),"triggered "+new Date());
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
****************************BroadCast Reciver Class***************
public class AlarmReceiver extends BroadcastReceiver {
private final static String TAG = "AlarmReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "onReceive()");
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
String current_date = dateFormat.format(date);
Logger.addRecordToLog(context,"AlarmReceiver","Received daily cup reminder "+current_date);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_daily_cup)
.setContentTitle(context.getString(R.string.daily_cup_reminder))
.setContentText(context.getString(R.string.daily_cup_message))
.setAutoCancel(true);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(context,0,resultIntent,PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(pendingIntent);
NotificationManager mNotificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}
}
Try this
Calendar calendar = Calendar.getInstance();
if (Calendar.getInstance().get(Calendar.HOUR_OF_DAY) >= 10) {
calendar.add(Calendar.DAY_OF_YEAR, 1); // add, not set!
}
calendar.set(Calendar.HOUR_OF_DAY, 10);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pi);
Try to set proper triggerAtTime (in the future) - like
Calendar.getInstance().getTimeInMillis()+(24*60*60*1000)
I am developing an app in which user can input times to set device in silent mode and back to normal when timer ends. Until now I can get the device in silent mode and back to normal mode but there is a delay after which silent mode is activated, delay is about of 10 or 15 seconds. I dont understand why silent mode is activated with a delay. Below is my code of start() and end() time functions.
start():
public void start()
{
Calendar cal=Calendar.getInstance();
// simpleDateFormat=new SimpleDateFormat("hh:mm a");
Date date = new Date();
//String time=simpleDateFormat.format(date);
int hour=cal.get(Calendar.HOUR);
int minute=cal.get(Calendar.MINUTE);
timePickerDialog=new TimePickerDialog(MainActivity.this, new
TimePickerDialog.OnTimeSetListener()
{
#Override
public void onTimeSet(TimePicker view, final int hourOfDay1,final int minute1) {
Time time = new Time(hourOfDay1, minute1,0);
GregorianCalendar j2=new GregorianCalendar(hourOfDay1,minute1,0);
System.out.println(j2);
//little h uses 12 hour format and big H uses 24 hour format
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("h:mm a");
//format takes in a Date, and Time is a sublcass of Date
String s = simpleDateFormat.format(time);
start.setText(s);
//dp.getDayOfMonth();
Calendar calNow = Calendar.getInstance();
Calendar calSet = (Calendar) calNow.clone();
calSet.set(Calendar.HOUR_OF_DAY, hourOfDay1);
calSet.set(Calendar.MINUTE, minute1);
Toast.makeText(MainActivity.this,"Starting Pending intent started",Toast.LENGTH_LONG).show();
//final int _id = (int) System.currentTimeMillis();
Intent intent = new Intent(getBaseContext(), SilenceBroadCastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), RQS_1, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, calNow.getTimeInMillis(), pendingIntent);
//final long sttimer=((shour)*60*60*1000)+((sminute)*60*1000);
}
},hour,minute,false);
timePickerDialog.setTitle("Set Start time");
timePickerDialog.show();
}
end()
public void end(){
Calendar cal1=Calendar.getInstance();
//simpleDateFormat1=new SimpleDateFormat("hh:mm a");
Date date1 = new Date();
//String time=simpleDateFormat1.format(date1);
int hour=cal1.get(Calendar.HOUR);
int minute=cal1.get(Calendar.MINUTE);
secondtimepickerdialog=new TimePickerDialog(MainActivity.this, new
TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker view, final int hourOfDay1,final int minute1) {
Time time = new Time(hourOfDay1, minute1,0);
GregorianCalendar j3=new GregorianCalendar(hourOfDay1,minute1,0);
//little h uses 12 hour format and big H uses 24 hour format
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("h:mm a");
//format takes in a Date, and Time is a sublcass of Date
String s1 = simpleDateFormat1.format(time);
end.setText(s1);
Calendar calNow1 = Calendar.getInstance();
Calendar calSet1 = (Calendar) calNow1.clone();
calSet1.set(Calendar.HOUR_OF_DAY, hourOfDay1);
calSet1.set(Calendar.MINUTE, minute1);
Toast.makeText(MainActivity.this,"End Pending intent started",Toast.LENGTH_LONG).show();
Intent intent = new Intent(getBaseContext(), UnsilenceBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), RQS_2, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, j3.getTimeInMillis(), pendingIntent);
//final long sttimer=((shour)*60*60*1000)+((sminute)*60*1000);
}
},hour,minute,false);
secondtimepickerdialog.setTitle("Set End time");
secondtimepickerdialog.show();
}
Solved......
In both the functions at onTimeset() I removed the final keyword and now somehow the delay is gone and device gets silent on the spot.
I am having some problem when trying to prompt notification based on the timing set by Alarm Manager in Android.
So what I am trying to do is a budget setting application. If the monthly expenses exceed the budget, it will prompt notification. In order to keep the question short, I will just post the part where I interact with Alarm Manager:
AlarmManager mgr = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Intent notificationIntent = new Intent(context, BudgetAlarm.class);
PendingIntent pi = null;
if (bm.getReminderNotify().equals("Y")
&& percentage >= 90) {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 1);
notificationCount = notificationCount + 1;
// Set request flag to 1 so that the same pending intent in broadcastReceiver
notificationIntent.putExtra("NotifyCount", notificationCount);
pi = PendingIntent.getBroadcast(context, 1,
notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
What I am trying to do here is to check if the expenses exceed the budget. And inside the BudgetAlarm class, I am prompting the notification:
private NotificationManager mNotificationManager;
private Notification notification;
#Override
public void onReceive(Context context, Intent intent) {
mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(context, 1,
new Intent(), 0);
notification = new Notification(R.drawable.ic_launcher, "Notification",
System.currentTimeMillis());
notification.setLatestEventInfo(context, "Budget Reminder",
"Your monthly expenses nearly exceed the budget!",
contentIntent);
mNotificationManager.notify(
Integer.parseInt(intent.getExtras().get("NotifyCount")
.toString()), notification);
}
My problem now is it does set and trigger the alarm manager every day. But let's say today I did not run the apps, it does prompt me a notification to notify me. But after a while, I launch the app, then it prompt me again.
I wonder is there any way to set the notification to just notify once per day regardless of how many times I launch the apps. I was actually thinking of something like cookies or shared preference.
Thanks in advance.
EDIT
public class BudgetAlarm extends BroadcastReceiver {
private NotificationManager mNotificationManager;
private Notification notification;
#Override
public void onReceive(Context context, Intent intent) {
saveDay(context);
if (sameDay(context) == false) {
mNotificationManager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
PendingIntent contentIntent = PendingIntent.getActivity(context, 1,
new Intent(), 0);
notification = new Notification(R.drawable.ic_launcher,
"Notification", System.currentTimeMillis());
notification.setLatestEventInfo(context, "Budget Reminder",
"Your monthly expenses nearly exceed the budget!",
contentIntent);
mNotificationManager.notify(
Integer.parseInt(intent.getExtras().get("NotifyCount")
.toString()), notification);
saveDay(context);
}
}
private boolean sameDay(Context context) {
boolean isSameDay = false;
SharedPreferences pref = context.getSharedPreferences("PrefKey",
Context.MODE_PRIVATE);
Calendar cal = Calendar.getInstance();
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy");
Date today = cal.getTime();
String day = format.format(today);
String savedDate = pref.getString("SaveDateKey", "NONE");
if (savedDate.equals(day)) {
isSameDay = true;
} else {
isSameDay = false;
}
return isSameDay;
}
private void saveDay(Context context) {
SharedPreferences pref = context.getSharedPreferences("PrefKey",
Context.MODE_PRIVATE);
Editor editor = pref.edit();
Calendar cal = Calendar.getInstance();
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy");
Date today = cal.getTime();
String day = format.format(today);
editor.putString("SaveDateKey", day);
editor.commit();
}
}
I think You are on the right way with shared preferences. This could be a scenario in Your app: make a method to know if the same day is equal, if not, save the date when You start the app:
private boolean sameDay(){
boolean isSameDay = false;
SharedPreferences pref = getApplicationContext().getSharedPreferences(YOUR_PREF_KEY, Context.MODE_PRIVAT);
Calendar cal = Calendar.getInstance();
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy");
Date today = cal.getTime();
String day = format.format(today);
String savedDate = pref.getString(YOUR_SAVED_DATE_KEY,"NONE");
if(savedDate.equals(day){
isSameDay=true;
}else{
isSameDay=false;
}
return isSameDay;
}
And to save the current day:
private void saveDay(){
SharedPreferences pref = getApplicationContext().getSharedPreferences(YOUR_PREF_KEY, Context.MODE_PRIVAT);
Editor editor = pref.edit();
Calendar cal = Calendar.getInstance();
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy");
Date today = cal.getTime();
String day = format.format(today);
editor.putString(YOUR_SAVED_DATE_KEY,day);
editor.commit();
}
And then You just handling this inside Your onReceive():
if(sameDay==true){
//donĀ“t notify
}else{
//notify and save the day
saveDay();
}
I have a date from DatePicker in
int year;
int month;
int day;
and time from TimePicker inint hour; int minutes;.
I need to create new alarm for this date, with notification. How I can do this?
I Have code :
public void addNotify(){
AlarmManager alarmManager = (AlarmManager) this.getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(year1, month1, day1, hour, minut);
Intent intent = new Intent(this, NotificationService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
As #Prmths said you probably haven't read anything on how to do that.
Have a look to the 'AlarmManager' class: link and with a bit of Google searching you should be able to achieve what you want to do.