How do i set Repeating Alarm for user selected days? - android

Condition :
User selects a active time period (from and to) for a day within which the alarm should be active with user specified interval.
User selects a inactive time period (from and to) for a day within which the alarm should be inactive or silent.
User selects the days on which the alarm should be fired.
eg: a user selects the active period of the alarm to be 9:00 am to 6:00pm with an interval of 20 minutes.
and he don't want the alarm to notify during his break time.say lunch break time is from 1:00 pm to 2:00 pm.He wasnts the alarm to be active only on Tuesday,Thursday and Sunday.
So during Tuesday, Thursday and Sunday ,the alarm should fire at 9:00am and fire with an interval of 20 minutes till 6:00pm. In between the alarm should be silent for 1:00pm to 2:00pm.
The user sets the timings in the main activity and the alarm for those timings is set in another activity where the alarm can be set and canceled.
Variables:
Active from time(in millisec) : int AFrom
Active to time (in millisec) : int ATo
Break from time (in millisec) : int BFrom
Break to time (in millisec) : int Bto
Alarm firing Interval (in millisec) : int interval
To select no: of days using a Android Alert Dialog with Multiple checkboxes:
String days[] = {"MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY","SUNDAY"} ;
Boolean checkedDays[] = {false,true,false,true,false,true,false};
final ArrayList DaysSelected = new ArrayList();
(this is just for information. Actual working Dialog box is created already. Just want to use the selected day's index for checking with the calendar day)
days[] is referenced with checkedDays[] to identify the selected days in setMultiChoiceItems().
Inside setMultiChioceItems():
builder.setMultiChoiceItems(days, checkedDays,
new DialogInterface.OnMultiChoiceClickListener() {
#Override
public void onClick(DialogInterface dialog, int selectedItemId,
boolean isSelected) {
if (isSelected) {
DaysSelected .add(selectedItemId);
} else if (DaysSelected .contains(selectedItemId)) {
DaysSelected .remove(Integer.valueOf(selectedItemId));
}
}
})
Alarm has to be set for the days whose checkedDays[] values are true
Note :All the variables all set static to use across all activities.
with the above variables how do I fire the below alarm for my above required condition?
Intent intent = new Intent(this,Notifier.class);
PendingIntent pendingIntent = PendingIntent.getActivitythis.getApplicationContext(),
12345, intent, FLAG_CANCEL_CURRENT );
AlarmManager am =(AlarmManager)getSystemService(Activity.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, AT_from , interval, pendingIntent);

Related

Several questions about Local notification

I'am not a new Codename One user but this is my first time to use Local notification with this framework. In my app, i have a picker to allow the user to choose a time (hour and minutes). i recevied the time which is chosen with getTime() method. Now i want my local notification to trigger at that time. What is the correct value that i need to give at the second parameter of the Display.getInstance().scheduleLocalNotification() function?
So far what I have is this sample but I don't understand how to apply it to my needs:
Display.getInstance().scheduleLocalNotification(notification, System.currentTimeMillis() + 10 * 1000, LocalNotification.REPEAT_NONE);
From the Java doc of that method
#param firstTime time in milliseconds when to schedule the
notification #param repeat repeat one of the following: REPEAT_NONE,
REPEAT_FIFTEEN_MINUTES, REPEAT_HALF_HOUR, REPEAT_HOUR, REPEAT_DAY,
REPEAT_WEEK
So you can use your Date object method getTime() to return the time in millis for that date object.
EDIT
Let's assume this is the callback for your time picker
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
Calendar date = Calendar.getInstance(); // This is the time now, so the day is set to today
date.set(Calendar.HOUR_OF_DAY, hourOfDay);
date.set(Calendar.MINUTE, minute);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.MILLISECOND, 0);
Display.scheduleLocalNotification(LocalNotification, date.getTime().getTime(), repeat);
}
Setting the second and millisecond is just to ensure the alarm goes off at the exact minute the user picked.
You can also change the day, month and year same as we changed the hour and minute.

start service which repeat at top of every hour and fetch information at fixed time interval

i have setting repeated alarm manager to start service which fetch the location and send SMS but currently i am only writing time duration in file to check the alarm accuracy .
I find that the alarm manager not working fine , i set for one hours interval but it fired at 30 min. interval . I left it for a day and find that after 12'o clock the alarm accuracy is right. What happening ??
My Activity class which start alarm :
enter code here
public static final long ALARM_TRIGGER_AT_TIME = SystemClock.elapsedRealtime() + 20000;
public static final long ALARM_INTERVAL = 1000 * 60 * 60 ;
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Intent myIntent = new Intent(AutoMainActivity.this, TrackerService.class);
pendingIntent = PendingIntent.getService(AutoMainActivity.this, 0, myIntent, 0);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,ALARM_TRIGGER_AT_TIME, 1000 * 60 * 60,pendingIntent);
AND my service class :
TraceService :
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
//writing in file to view time
java.util.Date systemDates = Calendar.getInstance().getTime();
simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
currentTime = simpleDateFormat.format(systemDates);
// create file and write current time
generateNoteOnSD("ONSTART"+currentTime+"\n","Onstart.txt");
}
After executing this apps at 3:18 PM time .The file created by service show the alarm time . Check this :
alarm manager time
ONSTART2013-05-13-15:18:26
ONSTART2013-05-13-15:21:58
ONSTART2013-05-13-15:54:21
ONSTART2013-05-13-16:18:25
ONSTART2013-05-13-17:18:26
ONSTART2013-05-13-17:49:21
ONSTART2013-05-13-18:18:25
ONSTART2013-05-13-19:18:28
ONSTART2013-05-13-20:10:51
ONSTART2013-05-13-20:18:29
ONSTART2013-05-13-20:48:49
ONSTART2013-05-13-21:18:30
ONSTART2013-05-13-21:58:58
ONSTART2013-05-13-22:18:38
ONSTART2013-05-13-22:56:00
ONSTART2013-05-13-23:18:43
ONSTART2013-05-13-23:48:49
ONSTART2013-05-14-00:18:44
ONSTART2013-05-14-01:18:45
ONSTART2013-05-14-02:18:45
ONSTART2013-05-14-03:18:45
ONSTART2013-05-14-04:18:45
ONSTART2013-05-14-05:18:44
ONSTART2013-05-14-06:18:44
ONSTART2013-05-14-07:18:44
You can check that when alarm manager start at 15:18 PM , it start again after 30 min. approx. But after 12'o clock it work fine !!! How to fix it. I need that alarm start every one hour not before that .
Try with AlarmManager.RTC_WAKEUP once instead of AlarmManager.ELAPSED_REALTIME_WAKEUP
There is an example in this : Alarm Manager Example
I suspect that you have multiple alarms pending. I would recommend that you clear out all of your alarms before you set this one.
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
// Cancel alarms
try {
alarmManager.cancel(intent);
} catch (Exception e) {
Log.e(TAG, "AlarmManager update was not canceled. " + e.toString());
}
}
(how to cancel alarms is answered well in this answer)
Not sure why everyone complicates this issue so much. I'm seeing it everywhere. Answers and answers about calculating the next hour.
There's absolutely no need to calculate anything. The the HOUR from the Calender and use that as the interval. The HOUR is called everytime the hour changes. That's all there really is to it.
Some devices may need a little tweaking to make sure the HOUR being called is not the same one for consecutive times. This is due to some devices calling the HOUR sometimes when the minute changes.

Android alarm: passed data is wrong if application is reinstalled

I have an application that uses alarms using AlarmManager. I set an alarm at a certain time and, when it triggers, it's set again 2 hours later. The second time the alarm is triggered it's not set again, so it's triggered just 2 times.
To know if the alarm triggered is the first one or the second I pass a boolean as a parameter to the BroadcastReceiver, like this:
Bundle b = new Bundle();
b.putBoolean(TODAlarm.KEY_IS_INFRACTION, true);
Intent intent = new Intent(me, TODAlarm.class);
intent.putExtras(b);
PendingIntent pendingIntent = PendingIntent.getBroadcast(me, TODAlarm.TYPE_DAILY_REST_NEEDED,
intent, PendingIntent.FLAG_ONE_SHOT);
alarmManager.set(AlarmManager.RTC_WAKEUP, time+2*HOURS, pendingIntent);
The first time I program the alarm I set KEY_IS_INFRACTION to false. When it's triggered I use the code from above and set it to true.
If I reinstall the application (using Eclipse->Run) when the alarm has been triggered once (I have an alarm programmed with KEY_IS_INFRACTION = true but it hasn't been triggered yet) the alarm programmed after the reinstall has KEY_IS_INFRACTION = false, but the intent received by the BroadcastReceiver has KEY_IS_INFRACTION = true (it seems like it receives the alarm programmed BEFORE reinstalling the application, even if I use alarmManager.cancel). This only happens when I reinstall the application, if I reboot the phone the intent received is ok. I always use alarmManager.cancel before alarmManager.set, but it's not working either.
The final application won't be reinstalled often, but if I publish an update this could lead to errors in the application behaviour. Anybody knows how can I fix it?
Here's the CORRECT sequence of actions (what the application should do):
1- Install aplication. Alarm is set to hour X with INFRACTION = false.
2- Hour X is reached and the alarm is triggered. The BroadcastReceiver receives an intent with INFRACTION = false and the alarm is set again with INFRACTION = true.
3- Reinstall application. Alarm is set to hour X with INFRACTION = false. Since hour X has already passed, the alarm is triggered. The BroadcastReceiver receives an intent with INFRACTION = false and the alarm is set again with INFRACTION = true.
Here's what it REALLY happens:
1- Install aplication. Alarm is set to hour X with INFRACTION = false.
2- Hour X is reached and the alarm is triggered. The BroadcastReceiver receives an intent with INFRACTION = false and the alarm is set again with INFRACTION = true.
3- Reinstall application. Alarm is set to hour X with INFRACTION = false. Since hour X has already passed, the alarm is triggered. The BroadcastReceiver receives an intent with INFRACTION = true and the alarm isn't set again.
[EDIT] Add some code. This is the function to set the alarm when the application is first started:
private void setNeededRestAlarmOrWarning(int type, long timeToStart){
Bundle b = new Bundle();
b.putInt(TODAlarm.KEY_ALARM_TYPE, type);
if(type == TODAlarm.TYPE_DAILY_REST_NEEDED){
b.putBoolean(TODAlarm.KEY_IS_INFRACTION, arr_bControls[CONTROL_PERMITIR_DORMIR_9_HORAS] ||
arr_iControls[CONTROL_LIMIT_TO_RECUPERATE] == 0 ||
arr_iControls[CONTROL_TIME_TO_RECUPERATE_COUNTER] >= Times.CTRL_PERMITTED_DESCANSOS_REDUCIDOS_POR_SEMANA);
Log.d(TAG, "INFRACTION IS "+b.getBoolean(TODAlarm.KEY_IS_INFRACTION));
}
Intent intent = new Intent(me, TODAlarm.class);
intent.putExtras(b);
PendingIntent pendingIntent = PendingIntent.getBroadcast(me, type,
intent, PendingIntent.FLAG_ONE_SHOT);
alarmManager.set(AlarmManager.RTC_WAKEUP, timeToStart, pendingIntent);
}
When the alarm is triggered I use the code posted above, before the EDIT.
[/EDIT]

How to start an alarm if the mobile is switch off

In my app, I use the AlarmManager class to set an alarm. To trigger the alarm after the mobile is rebooted I have used BroadcastReceiver. All works fine and my alarm is triggered at regular intervals. Now the problem arises in this case :
Suppose my current time is 2:30 pm and I set my alarm at 2:35 pm. After that, I switch off the mobile. After an hour when I switch on my mobile, no alarm is pop-up as the time on which the alarm is set. This is happening because the current time exceeds the time on which I set the alarm. To solve this issue what should I do. I have posted my code for setting alarm in the AlarmManager class. Please help me to solve this out
public class AlarmReceiver extends BroadcastReceiver {
#SuppressWarnings("static-access")
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {
Intent myIntent = new Intent(context, MyAlarmService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, i, myIntent, i);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.MILLISECOND, (int) Utilities.diff(NoteManager.getSingletonObject().getAlarmTime(i)));
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
}
}
public static long diff(Date date) {
long difference = 0;
try {
// set current time
Calendar c = Calendar.getInstance();
difference = date.getTime() - c.getTimeInMillis();
if (difference < 0) {
// if difference is -1 - means alarm time is of previous time then current
// then firstly change it to +positive and subtract form 86400000 to get exact new time to play alarm
// 86400000-Total no of milliseconds of 24hr Day
difference = difference * -1;
difference = 86400000 - difference;
}
}
catch (Exception e) {
e.printStackTrace();
}
return difference;
}
In The Manifest File
<receiver android:name=".AlarmReciever">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
better way is to store that alarm details in database and retrieve it on boot via broadcast receiver as you are saying you implemented one. once notified remove the details from the database. this way u can track all your alarms. even you can start a Service on startup and do this operation
The Alarm app in the Android does the same, if your phone is switched off and there is Alarm to ring up, It will make your phone switch On , ring the alarm and go to sleep again.
Here is the link of source of Alarm app Git_Alarm app you can download it and see how it is doing this.
and if you are doing something else in your alarm reciever then to ring Alarm up. you can basically set alarmreciever again in the phone Boot up, here is the one answer which may help you Alarm problem if phone is switched off
Edit :- one link was broken, replaced it

I want to schedule task at particular time for different day(Monday, Tuesday, etc) in android

Currently I am working on BroadcastReceiver, Service & AlarmManager in Android to developed one of functionality in my project. I need to schedule some task at particular time on particular day.
For E.g :-
Monday - 09:00 AM & 05:00 PM
Tuesday - 09:00 AM & 05:00 PM
Wednesday - 09:00 AM & 05:00 PM
Thursday - 09:00 AM & 05:00 PM
Friday - 09:00 AM & 05:00 PM
Saturday - 10:00 AM & 10:00 PM
Sunday - 10:00 AM & 10:00 PM
What i have done till now is created one activity & broadcastreceiver. On click of button, after every 60seconds broadcast receiver will be called. Here is my code snippet. But i want to schedule my task according to the week that i have described above. Can anyone please kindly help me how can i schedule the task like above.
Code :-
public class AlarmDemoActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonStart = (Button)findViewById(R.id.start);
buttonStart.setOnClickListener(new Button.OnClickListener(){
public void onClick(View arg0) {
// TODO Auto-generated method stub
Intent myIntent = new Intent(getBaseContext(),
MyScheduledReceiver.class);
PendingIntent pendingIntent
= PendingIntent.getBroadcast(getBaseContext(),
0, myIntent, 0);
AlarmManager alarmManager
= (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 10);
long interval = 60 * 1000; //
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), interval, pendingIntent);
finish();
}});
}
}
BroadcastReceiver :-
public class MyScheduledReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
/*Intent scheduledIntent = new Intent(context, MyScheduledActivity.class);
scheduledIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(scheduledIntent);*/
System.out.println("Make Phone Silent");
}
}
All suggestion and tips are welcomed.
I will give the idea for this at a very high level.You will have to figure out the coding your self:
1.Save the user preferences in shared preferences(which I presume you are already doing)
2.Schedule the first alarm using the set method of Alarm Manager
Refer this for details on this method.
3.When that alarm goes off,again schedule the next alarm using the next time period in Shared Preferences,again using the set method
You don't need to call it every 60 seconds, you can set the time when it should be fired into an alarm using your calendar instance and setting the correct dates, so alarm manager will fire the broadcast intent at specified dates and times.
Beware that if the phone is turned of the alarm manager will be reset so you have to store the alarms in any persistent storage and register a broadcast receiver for the BOOT_COMPLETED action to restore the alarms.
You can test with small intervals so you won't have to wait the whole day :)

Categories

Resources