I have used AlarmManager to set the alarm and passed the time from timePicker.
I want to set alarm at the given time but if the time(that I am going to set) has been passed then the alarm triggers immediately .
Example:- If the current time is 9:00 PM and I set alarm for 7:00PM then the alarm triggers immediately.
Below is my code
public void startAlarm(Calendar c, int id){
Toast.makeText(this, "Alarm in on", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this,AlarmReciever.class);
intent.putExtra("id",id);
//int _id = (int)System.currentTimeMillis();
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,id,intent,PendingIntent.FLAG_ONE_SHOT);
alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,c.getTimeInMillis(), 1000*60,pendingIntent);
//alarmManager.set(AlarmManager.RTC_WAKEUP,c.getTimeInMillis(),pendingIntent);
}
How to control the triggering of alarm if the time for which we are setting alarm has been passed?
You will need to detect if the calendar time is in the past and adjust it accordingly. Like so:
public void startAlarm(Calendar c, int id){
Toast.makeText(this, "Alarm in on", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this,AlarmReciever.class);
intent.putExtra("id",id);
//Check if calendar is set in the past
if (c.getTimeInMillis() < System.currentTimeMillis()) {
//Add one day to the calendar (or whatever repeat interval you would like)
c.add(Calendar.DAY_OF_YEAR, 1);
}
//int _id = (int)System.currentTimeMillis();
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,id,intent,PendingIntent.FLAG_ONE_SHOT);
alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,c.getTimeInMillis(), 1000*60,pendingIntent);
//alarmManager.set(AlarmManager.RTC_WAKEUP,c.getTimeInMillis(),pendingIntent);
}
As I'm not sure how you are allowing the user to set the time I'm not sure if the addition of one day will always do the trick. For instance, if you allow the user to pick a date from a calendar it may be years in the past. You will need to adjust how much time you add based on your desired repeat interval and how you are allowing the user to set the time.
Related
I've built one small reminder app demo. Now the problem is sometimes reminder coming or sometimes not? Now, I have this feature that user can set the alarm for day, month, week, year.
Now how can I check for the month or year that notification is coming or not?
Obviously, when I manually go and change the Android date and time settings, alarm not coming. (Even for some minutes also)
See: When I change Android phone date and time, notification not getting, otherwise, if I do nothing, I get notification on time
Edit:
Code:
public void setRepeatAlarm(Context context, Calendar calendar, int ID, long RepeatTime, int requestCode) {
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// Put Reminder ID in Intent Extra
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra(REMINDER_ID, Integer.toString(ID));
mPendingIntent = PendingIntent.getBroadcast(context, ID, intent, PendingIntent.FLAG_CANCEL_CURRENT);
mPendingIntent = PendingIntent.getBroadcast(context, requestCode, new Intent(context, AlarmReceiver.class),
PendingIntent.FLAG_NO_CREATE);
isAlarmSet = (mPendingIntent != null);
if (isAlarmSet) {
showLog("isAlarmSet: " + isAlarmSet);
} else {
showLog("isAlarmSet: " + isAlarmSet);
}
// Calculate notification timein
Calendar c = Calendar.getInstance();
long currentTime = c.getTimeInMillis();
long diffTime = calendar.getTimeInMillis() - currentTime;
// Start alarm using initial notification time and repeat interval time
mAlarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + diffTime,
RepeatTime, mPendingIntent);
// Restart alarm if device is rebooted
ComponentName receiver = new ComponentName(context, BootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
You can check for existing alarm using this :
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, requestCode,
new Intent(this, AlarmReceiver.class),
PendingIntent.FLAG_NO_CREATE);
boolean isAlarmSet = (pendingIntent!=null);
Note that the requestCode here should be the same one used while setting the alarm. Also, AlarmReceiver is your BroadcastReceiver class for alarm
I have not tested this in the scenario you mentioned (changing the phone time), but you can refer this and set your alarm again according to the new time and cancel the previous one.
You have pretty knowledge about Design Pattern. Please follow the Observer Pattern to mange below thing and get always new time when you change time manually or not. It will check current time is changed or not. More details Please read Observer Pattern Documentation.
// Calculate notification timein
Calendar c = Calendar.getInstance();
long currentTime = c.getTimeInMillis();
long diffTime = calendar.getTimeInMillis() - currentTime;
You should listen to time changes in the android system and act accordingly
<receiver android:name=".TimeChangedReceiver">
<intent-filter >
<action android:name="android.intent.action.TIME_SET"/>
</intent-filter>
</receiver>
Broadcast receiver class
public class TimeChangedReceiver extends BroadcastReceiver{
#Override
public void onReceive(final Context arg0, Intent arg1) {
//Call your Alarm setting code
// change your alarm accordingly
}
}
I am trying to implement alarm that notify daily at the same time. It works fine. But when i set alarm again it notify me on the spot without waiting time to come, because time on which alarm is set has been passed. But when I change Calendar.DATE to Calendar.DAYS_OF_MONTH it does not notify me. So can any one help me where i am wrong. I am sharing my code below.
public void setNotification() {
PendingIntent pendingIntent = createPendingIntent();
Calendar calendarToSet=Calendar.getInstance();
Calendar currentTime=Calendar.getInstance();
calendarToSet.set(Calendar.HOUR,10);
calendarToSet.set(Calendar.MINUTE,0);
calendarToSet.set(Calendar.SECOND,0);
calendarToSet.set(Calendar.AM_PM,Calendar.AM);
if(calendarToSet.before(currentTime))
{
calendarToSet.set(Calendar.DATE,1);
}
AlarmManager alarmManager = (AlarmManager) MyAppManager.context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,calendarToSet.getTimeInMillis(),AlarmManager.INTERVAL_DAY,pendingIntent);
// Toast.makeText(MyAppManager.context, "set", Toast.LENGTH_LONG).show();
}
public PendingIntent createPendingIntent() {
Intent intent = new Intent(MyAppManager.context, TaffaquhFiddinBroadCastReceiver.class);
intent.putExtra("key", "What_to_say_upon_completing_ablution");
PendingIntent pendingIntent = PendingIntent.getBroadcast(MyAppManager.context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
What i am trying to do is to set alarm for the next day if the time is passed so please help.
Also what is the difference between Calendar.DATE and Calendar.DAYS_OF_MONTH?
The problem is you are setting the day field of your Calendar instance, instead of adding a day to it.
Change the following:
calendarToSet.set(Calendar.DATE, 1);
To this:
calendarToSet.add(Calendar.DATE, 1);
Also what is the difference between Calendar.DATE and
Calendar.DAYS_OF_MONTH?
They are the same, DATE is just a synonym for DAY_OF_MONTH.
From the source code of the Calendar class:
public static final int DATE = 5;
public static final int DAY_OF_MONTH = 5;
As you can see, they represent the same value.
I am doing a reminder application. It will reminder for a duration at the interval of time. For example, remind every five minutes for an hour. In this case, I am trying to set two alarm. One is used to do the reminder for every five minutes, the other one is used to cancel the reminder alarm after one hour. Here is my codes.
private void createIntervalNotification(int reminder, int dhour, int dminute){ //reminder in min
int interval = (reminder)*60*1000;
AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(MainActivity.this.ALARM_SERVICE);
am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+interval, interval, getPendingIntent(this,REMINDER_ID));
int duration = (dhour*60 + dminute)*60*1000;
am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+duration,getPendingIntent(this,CANCEL_REMINDER_ID));
}
private static PendingIntent getPendingIntent(Context ctxt, int id) {
Intent intent1 = new Intent(ctxt, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(ctxt, id,intent1, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
I have some questions to do this(Set reminder of 5 mins for duration of 1 hour).
1) Can I do this with my method? Use one alarm to cancel another?
2) Can both alarm share a broadcastReceiver? If yes, how to differentiate it is invoked by which alarm?
3) Is it any other method can do this?
Cancelling an alarm is pretty much exactly the same as setting an alarm. You just call a different method to cancel on the AlarmManager than you do to create. Just make sure that the pending intent in the AlarmManager and the broadcast ID is identical.
Differentiate alarms by setting Extras on the Intent.
I have a scheduleAlarm class which is supposed to set the alarm in a specific time, however the alarm is being fired immediately after the method is called. I've checked that provided time in milliseconds is fine, so I've no idea what's going on.
private void scheduleAlarm(int day, int startHour, int startMinute, String info) {
AlarmManager mAlarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar c = Calendar.getInstance();
c.set(Calendar.DAY_OF_WEEK, day);
c.set(Calendar.HOUR, startHour);
c.set(Calendar.MINUTE, startMinute);
Intent startIntent = new Intent(this, Recorder.class);
startIntent.putExtra("info", "someinfo");
Log.v("millis", String.valueOf(c.getTimeInMillis())); // time is okay
Random mRandom = new Random();
int randomInt = mRandom.nextInt();
PendingIntent pendingIntent = PendingIntent.getService(this, randomInt, startIntent,PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pendingIntent);
}
Just make sure that the time set for the alarm is after current time.
There is an easy way to check that.
just do
Calendar.getInstance().getTimeInMilis() - c.getTimeInMillis()
Log this result, and you can see if the second is before the first.
Lets say now is 4 o'clock, and you set the same day and 3 o'clock. it will get activated instantly.
Other than that i see no reason why it should fail.
Another way to test would be to use currentTime and add lets say 10k miliseconds and see if it activates in 10 seconds after you test it. Then you are sure that the time set is wrong in your case.
Ok, let me modify the question and make it much easier. I Hope you'll be able to get me the solution for this. Both the alarms should be scheduled simultaneously, which is not happening here. I am even using unique requestcode for the pending intent. HELP ME please.....
//On click Listener
private OnClickListener mOneShotListener = new OnClickListener() {
public void onClick(View v) {
Intent intent = new Intent(AlarmController.this, OneShotAlarm.class);
PendingIntent sender = PendingIntent.getBroadcast(AlarmController.this,0, intent, 0);
//I even tried sender = PendingIntent.getBroadcast(AlarmController.this,0, intent, PendinIntent.FLAG_UPDATE_CURRENT);
//the alarm to go off 30 seconds from now.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 30);
// Schedule the alarm!
AlarmManager am = (AlarmManager)getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender);
//adds 2 minutes to the time
calendar.add(Calendar.MINUTE, 2);
sender = PendingIntent.getBroadcast(AlarmController.this,1, intent,0);
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), sender2);
}
};
OLD Question:
I want to set two alarms at the same time for two different operations to be performed.
For Eg. A user sets alarm at 2'O clock and sets the duration to 15 mins. The first alarm should fire at 2'O clock which performs function1 and the second alarm should fire at 2:15 as the user specified the duration as 15 mins which performs the function2. This operation should be repeated everyday at 2'O clock unless the user changes the time.
I am calling this both functions on button click:
On Click Event
saveButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
..........
..........
new ReminderManager(this).setReminder(mRowId, mCalendar);
new ReminderManager(this).wakeReminder(mRowId, mCalendar, duration);
}
}
The setReminder contains
//sets alarm at 2'O clock
public void setReminder(Long taskId, Calendar when, String duration){
Intent i = new Intent(mContext, OnAlarmReceiver.class);
i.putExtra(RemindersDbAdapter.KEY_ROWID, (long)taskId);
PendingIntent pi = PendingIntent.getBroadcast(mContext,(int)System.currentTimeMillis(), i, PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, when.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
}
The wakeReminder contains
//adds duration i.e. 15mins
public void wakeReminder(Long taskId, Calendar when, String duration){
Intent i = new Intent(mContext, OnAlarmReceiverWake.class);
i.putExtra(RemindersDbAdapter.KEY_ROWID, (long)taskId);
Long d = Long.parseLong(duration);
Long mins = d*60*100;
Long milli = when.getTimeInMillis() + mins;
PendingIntent pi = PendingIntent.getBroadcast(mContext, (int)System.currentTimeMillis(), i, PendingIntent.FLAG_UPDATE_CURRENT);
mAlarmManager.set(AlarmManager.RTC_WAKEUP, milli, pi);
}
I have noticed that whenever mAlarmManager.set(); is executed successfully the LogCat shows notification like
"enqueueToast pkg=com.jellboi.android.togglemode callback=android.app ITransientNotification$stub$proxy#43c0c5f8 duration=0"
but when I set both the alarms simultaneously the notification is not shown when the mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, when.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi); is executed
but the notification is shown when mAlarmManager.set(AlarmManager.RTC_WAKEUP, milli, pi); is executed. Also the notification is set for the original time i.e. 2'O clock and not after adding 15mins to it's duration.
Please help, I tried a lot of ways to call this functions at different places like after the 1st alarm is fired but all in vain.
PendingIntent sender = PendingIntent.getBroadcast(AlarmController.this,0, intent, 0);
You have problem in this line. If you want to simultaneously fire two alarma then you should do something like this
PendingIntent sender = PendingIntent.getBroadcast(AlarmController.this,giveUniqueRequestIdsHere, intent, 0);
sender = PendingIntent.getBroadcast(this, (int) System.currentTimeMillis(), i, PendingIntent.FLAG_ONE_SHOT);
Do the same for your PendingIntent.getActivity();
Hi try using this to generate request I was generating my own request code but this line worked for me
final int intent_id = (int) System.currentTimeMillis();
When launch new OneShotAlarm.class, it have to design launch mode. Default setting would ignore the second time launch, if the first instance still existed.
Intent intent = new Intent(AlarmController.this, OneShotAlarm.class);
intent.setFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
seems like you forgot to set "sender2" before your second call.
you change the value of sender, then put sender2 as the argument.
You can create an array of your task in the Service class and set the array in the for loop, inside the for loop you can call your task simultaneously at the same time.
Try this:
Calendar cal = new GregorianCalendar();
Date date = cal.getTime();
cal.clear();
Cursor c = database.query(mArray.get(mPosition), new String[]{"days"},"days"+"!="+0, null, null, null, null);
cal.set(Calendar.YEAR,2011);
cal.set(Calendar.MONTH,date.getMonth());
cal.set(Calendar.DAY_OF_MONTH,date.getDate());
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, min);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
AlarmManager mgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(nextScreen.this, AlaramReciver.class);
i.putExtra("Start",mArray.get(mPosition));
Editor medit = getSharedPreferences("Start", 0).edit();
medit.putString("Start", mArray.get(mPosition));medit.commit();
PendingIntent pendingintent = PendingIntent.getBroadcast(this,mPosition, i, 0);
mgr.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingintent);
You have set to the time like this, and once you set time in alarm manager it will automatically call the functions daily. Use different request code for pendingintent.
If you want call second function. You just add the time in 15 min in the
cal.set(Calender.MINUTE,min+15);