I have two time picker and spinner with value 1 to 10, I want to make number of local notification selected from spinner between time selected from two time picker for eg from 2 pm to 6 pm I want to show six notification and it should notify every day between selected time range with selected value, I have used alarm manager for this but it showing just one notification also used set repeating.
Also I tried to first find time difference from two picker in millis and applied some logic but nothing seems to be good. Please give me some logic or sample code will be appreciated.
Some code snippet is
Intent myIntent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
myIntent, 0);
long next = 0;
for (int i = 0; i < spinnervalue ); i++) {
Log.e("checkkkk ", "" + "checkkkk");
alarmManager.set(AlarmManager.RTC_WAKEUP, next, pendingIntent);
next += diff_millis;
}
This snippet should work, perhaps with a few changes.
Here i am getting the difference between the 2 time pickers in milliseconds and += to the current time in milliseconds. Giving each pending intent a different ID and telling it to update and existing one if available (allows you to reset them if you know the ID (counter).
You have to divide the difference by the spinner chosen in order to get evenly spaced millisecond differences.
//Assume timepicker2 > timepicker1
int hours1 = timePicker1.getCurrentHour();
int minutes1 = timePicker1.getCurrentMinute();
int hours2 = timePicker2.getCurrentHour();
int minutes2 = timePicker2.getCurrentMinute();
int hourDiff = hours2-hours1;
int minutesDiff = minutes2-minutes1
int millisecondsDiff = hourDiff*60*60*1000;
millisecondsDiff += minutesDiff*60*1000;
Double period_diff = millisecondsDiff/spinnerValue;
//This is for the intent difference
int counter = 0;
long next = System.currentTimeMillis() + period_diff;
for (int i = 0; i < spinnervalue ); i++) {
Intent myIntent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, counter++, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
Log.e("checkkkk ", "" + "checkkkk");
alarmManager.set(AlarmManager.RTC_WAKEUP, next, pendingIntent);
next += period_diff;
}
Don't take the snippet to work definitively as it's a quick jot down, but it should give you a general idea of where you should be looking.
Another idea would be to use i as the counter so you know in what range the IDs are.
http://developer.android.com/reference/android/app/AlarmManager.html#set%28int,%20long,%20android.app.PendingIntent%29
If the stated trigger time is in the past, the alarm will be triggered
immediately. If there is already an alarm for this Intent scheduled
(with the equality of two intents being defined by
filterEquals(Intent)), then it will be removed and replaced by this
one.
So setting this in a loop isn't what you want.
Your value for millis needs to be a time. 0 would indicate epoch (January 1st, 1970). What you probably want is "SystemClock.elapsedRealtime() + someValue" passed in for that parameter.
Related
I have a mostly working alarm that functions perfectly except for one aspect: The time that I have set for the alarm to trigger is not always the time that it triggers at.
I was thinking for a while that maybe the alarm ran in seconds, not milliseconds. After rereading the documentation, this thought was dismissed.
I'm going to post the important code now before I explain a bit more:
BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
startAlarm(findViewById(R.id.reset));
Log.d("test", "reseting");
}
};
public void startAlarm(View view) {
//setup
EditText nameInput = (EditText) this.findViewById(R.id.nameInput);
EditText firstAlertInput = (EditText) this.findViewById(R.id.firstAlertInput);
EditText intervalInput = (EditText) this.findViewById(R.id.intervalInput);
EditText descriptionInput = (EditText) this.findViewById(R.id.descriptionInput);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = sp.edit();
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
//Need to parse and format the offset now, before intent is created, then attach it to the intent.
//HERE I NEED TO GET THE OFFSET AND CONVERT INTO MILLISECONDS
EditText hoursInput = (EditText) this.findViewById(R.id.hoursInput);
EditText minutesInput = (EditText) this.findViewById(R.id.minutesInput);
EditText secondsInput = (EditText) this.findViewById(R.id.secondsInput);
int hours = 0;
int minutes = 0;
int seconds = 0;
try {
hours = Integer.parseInt(hoursInput.getText().toString()) * 3600000;
minutes = Integer.parseInt(minutesInput.getText().toString()) * 60000;
seconds = Integer.parseInt(secondsInput.getText().toString()) * 1000;
} catch(NumberFormatException e) {
}
int offsetMillis = hours + minutes + seconds;
//HERE: Randomly Generate the offset, add or subtract it when alarm is set. Make sure to attach the opposite to the PI so that the next alarm will trigger at te correct default time
int offsetRandomMillis = 0;
if(offsetMillis != 0){
Random offsetRandom = new Random();
int oneOrNegativeOne = (offsetRandom.nextBoolean()) ? 1 : -1;
offsetRandomMillis = offsetRandom.nextInt(offsetMillis) * oneOrNegativeOne;
}
//Creates new offset alarm structure
Intent intent = new Intent(this, AlarmReciever.class);
intent.putExtra("name", nameInput.getText().toString());
intent.putExtra("description", descriptionInput.getText().toString());
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 234324243, intent, PendingIntent.FLAG_UPDATE_CURRENT);
//Creates new recursion alarm structure
Intent intent2 = new Intent("RESET_ALARM");
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(this.getApplicationContext(), 000, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
//Stores old offset alarm details
editor.putString("oldName", nameInput.getText().toString());
editor.putString("oldDescription", descriptionInput.getText().toString());
editor.apply();
//Finishes new offset alarm details
int[] times = parseTime(firstAlertInput.getText().toString());
times[0] = times[0] * 3600000;
times[1] = times[1] * 60000;
long millis = times[0] + times[1];
int[] intervalTimes = parseTime(intervalInput.getText().toString());
intervalTimes[0] = intervalTimes[0] * 3600000;
intervalTimes[1] = intervalTimes[1] * 60000;
long intervalMillis = intervalTimes[0] + intervalTimes[1];
//New offset alarm set
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + millis + intervalMillis + offsetRandomMillis, pendingIntent);
//New Recursion alarm set
alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + millis + intervalMillis, pendingIntent2);
Log.d("test", "OFFSET: " + String.valueOf((System.currentTimeMillis() + millis + intervalMillis + offsetRandomMillis) / 1000));
Log.d("test", "NOOFFSET: " + String.valueOf((System.currentTimeMillis() + millis + intervalMillis) / 1000));
}
private int[] parseTime(String input){
int[] times = new int[2];
String[] split = input.split(":");
for(int i = 0; i < times.length; i++){
times[i] = Integer.parseInt(split[i]);
}
return times;
}
NOTE: These are both in the same class, and I am excluding irrelevant parts of that same class.
So here is what is happening: After I clear all alarms and set new ones, those alarms trigger at the correct time. When the broadcastReceiver sets the new alarms, these alarms trigger 5-20 seconds late. All subsequent alarms that it sets also trigger late, but they trigger 5-20 seconds later than the previous alarms. As you can see, the alarm ends up triggering far fewer times than in should.
Also, note that this experiment was tested with an interval value of 1 minute, meaning that each alarm should have triggered one minute after it was set. I know there is also code that determines and parses an offset, but I have no set a value for that, so it doesn't affect the time. I printed this value among many other values, so I know that this works.
I'm frustrated because I see no reason why this should fail. The current log.d statements in the code that I posted are just to show when a new alarm is set and the time in which both alarms should go off (one alarm is suppose to trigger a notification, this one that adds the offset. The other triggers without the offset and sets the new alarms. Sorry if I confused you.). These values are correct, so that is not an issue.
My suspicion at the moment comes from another experiment that I performed. I continually clicked the button that first runs the startAlarm method. This displayed the time in milliseconds that the alarms that were set should have triggered. I expected this number to rise constantly as 1000 milliseconds must pass in one second. This was not the case however. The number rose slowly, about 10 every few. This was a very unexpected behavior. Can someone please explain the reason for this in their answer as well? Thanks.
My current suspicion is that I have failed to convert something into milliseconds or into seconds. But, looking through the code and logging variables, I don't know that this is the issue. The milliseconds that pass seem to be funky, so I don't know what is up.
I want to trigger repeating alarm at specific time & I'm using below code but it does not trigger the alarm at the time I wanted.
boolean weeklyAlarmUp = (PendingIntent.getBroadcast(ctxt, 0, new Intent(ctxt, ScheduledWeeklyService.class), PendingIntent.FLAG_NO_CREATE) != null);
if (!weeklyAlarmUp) {
AlarmManager mgr = (AlarmManager)ctxt.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(ctxt, ScheduledWeeklyService.class);
PendingIntent pi = PendingIntent.getBroadcast(ctxt, 0, i, 0);
Date date = null;
try {
date = (Date) formatter.parse("17-Mar-2014 13:10:00"); // This date & time will be an user input from some activity
} catch (ParseException e) {
e.printStackTrace();
}
long triggerWeeklyTaskAt = date.getTime();
long currentTime = System.currentTimeMillis();
// Don't trigger the alarm is input date time is in the past, set it to next day but at the same time
if (currentTime > triggerWeeklyTaskAt) {
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, 13);
c.set(Calendar.MINUTE,10);
c.set(Calendar.SECOND,0);
c.set(Calendar.MILLISECOND, 0);
c.add(Calendar.DATE, 1);
date = c.getTime();
triggerWeeklyTaskAt = date.getTime();
}
Locale locale = Locale.getDefault();
msgFormatter.setLocale(locale);
Object[] objs = { "Dummy" };
SchedulerLog.logInfo(ctxt, ctxt.getString(R.string.module_scheduler), msgFormatter.format(objs));
mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, triggerWeeklyTaskAt, PERIOD_WEEKLY, pi);
}
Can anyone tell me what is wrong in below code? How can I check what time it'll trigger alarm at?
Thanks
Your outer if statement looks a bit weird. Are you sure execution is making it inside of it? Throw in a Log statement and/or step through the code to make sure.
If I understand your logic, you're attempting to not create a duplicate PendingIntent. So if the PI already exists, you bypass the whole body of the if. The problem with that is that your alarm setup is inside the if statement too.
The reference page says "...even if its owning application's process is killed, the PendingIntent itself will remain usable from other processes that have been given it." So perhaps a matching PI still exists from a previous run? It might be better to always (re)create the PI, but use FLAG_CANCEL_CURRENT or FLAG_UPDATE_CURRENT depending on whether you want to update the particulars.
Hi I am trying to create multiple alarms.
I am getting the number of hours left in the day, dividing it by the number of alarms needed, then trying to set alarms with intervals between them.
So for example if num of alarms is 2, and user clicks button at 14:00 there are 10 hours left, so 10 hours / 2 alarms = 5 hours distance between each alarm
So I want to set 2 alarms (one alarm at 19:00 and another at 24:00)
Currently my code is only setting 1 alarm and seems to ignore running the for loop multiple times. I'm not sure why the for loop dosnt create multiple alarms
try {
// Current Time
Time timeNow = new Time();
timeNow.setToNow();
int timeNowHour = timeNow.hour;
int timeNowMins = timeNow.minute;
// Hours left in day
int hoursInADay = 24;
int hoursLeftInDay = hoursInADay - timeNowHour;
// Number of alarms
int numAlarms = 2;
// Calc time between each alarm
int alarmDistance = hoursLeftInDay / numAlarms;
for(int i = 0; i < numAlarms; i++){
int alarmHour = timeNowHour + alarmDistance * (i+1);
Intent alarmIntent = new Intent(AlarmClock.ACTION_SET_ALARM);
alarmIntent.putExtra(AlarmClock.EXTRA_MESSAGE, "TEST ALARM");
alarmIntent.putExtra(AlarmClock.EXTRA_HOUR, alarmHour);
alarmIntent.putExtra(AlarmClock.EXTRA_MINUTES, timeNowMins);
alarmIntent.putExtra(AlarmClock.EXTRA_SKIP_UI, true);
alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(alarmIntent);
}
} catch (Exception e) {
}
Thanks
AlarmManager alarmManager= (AlarmManager)getSystemService(ALARM_SERVICE);
PendingIntent intent=createPendingResult(ALARM_TIME_ID, new Intent(), 0);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME,SystemClock.elapsedRealtime() + alarmDistance,alarmDistance, intent);
And in the onActivityMethod you can do whatever you want.
Example:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ALARM_TIME_ID) {
Toast.makeText(this, "Alarm is running", Toast.LENGTH_LONG).show();
}
Make sure to set the ALARM_TIME_ID to a unique int value.
I have an app that needs to set alarms for multiple days of the week, depending on what days the user sets them. I have it working where it triggers an alarm at the appropriate time, but am wanting to know how to do multiple without them overridding the current AlarmManager. For example, here is my test code:
final int alarmid = (int)System.currentTimeMillis(); //creates unique id for the alarm attached to the object
tempmainfrag.mainObjectList.returnSchedule(i).setAlarmId(alarmid);
for(int j = 0; j < 7; j++)
{
if(tempmainfrag.mainObjectList.returnSchedule(i).returnDays()[j]) //if this day of the week has an alarm
{
int adjustedday = j+2; //makes time for DAY_OF_WEEK where sunday = 1, monday = 2, etc.
if (adjustedday == 8)
adjustedday = 1;
Calendar startcal = Calendar.getInstance();
startcal.set(Calendar.DAY_OF_WEEK, adjustedday);
startcal.set(Calendar.HOUR_OF_DAY, tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[0]);
startcal.set(Calendar.MINUTE, tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[1]);
startcal.set(Calendar.SECOND, 0);
Log.i("mydebug","Starting cal day of week: " + adjustedday);
Log.i("mydebug","Starting cal hour of day: " + tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[0]);
Log.i("mydebug","Starting minute: " + tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[1]);
Intent intent = new Intent(this, SilenceHandler.class);
intent.putExtra("starttime",tempmainfrag.mainObjectList.returnSchedule(i));
intent.putExtra("alarm_message", "Test!"); //FOR TESTING
PendingIntent pendintent = PendingIntent.getBroadcast(this, alarmid, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmman = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmman.setRepeating(AlarmManager.RTC_WAKEUP, startcal.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 7, pendintent);
// startcal.set(Calendar.MINUTE, (tempmainfrag.mainObjectList.returnSchedule(i).returnTimes()[1])+1);
// alarmman.setRepeating(AlarmManager.RTC_WAKEUP, startcal.getTimeInMillis(), AlarmManager.INTERVAL_DAY * 7, pendintent);
}
}
The for loop iterates through days of the week, and at each iteration checks to see if the alarm should be set for that day. This code works (presumably), but to test if I could set another alarm on top of it I added in the last two lines of code that are commented out here. This makes the alarm go off a minute later, but not a minute earlier as well. I am doing this to demonstrate that if I want this code to work for multiple days of the week, the way the code is currently set up will just have the alarm set for the last day of the week that returns true. How can I make multiple alarms?
The problem is that although you are creating a unique ID for your PendingIntent, which would set separate alarms, in your test you are reusing the same PendingIntent, which would override your previous one. Create a new PendingIntent with a different alarmid to test this.
I am trying to make an alarm application that takes multiple "n" time inputs from the user and rings at those particular times. For that I have created an array of EditTexts for both the hour and minute entries. In the onclick listener for the start button, I wish to have alarm managers for all the entered time inputs initialized.
After creating an array of calendar, should i create an array of intents and pending intents and alarm manager objects also--one each for each calendar object?
This is the code for my start button:
public void setAlert(View view) {
int length = editHour.length;
int h[] = new int[length];
int m[] = new int[length];
Calendar[] cal = new Calendar[length];
for (int i = 0; i < length; i++) {
cal[i] = Calendar.getInstance();
}
for (int i = 0; i < length; i++) {
try {
m[i] = Integer.parseInt(editHour[i].getText().toString());
h[i] = Integer.parseInt(editMinute[i].getText().toString());
cal[i].set(Calendar.HOUR, h[i]);
cal[i].set(Calendar.MINUTE, m[i]);
Intent intent = new Intent(this, AlarmService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
12345, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP,
cal[i].getTimeInMillis(), pendingIntent);
Toast.makeText(this, "Alarm set", Toast.LENGTH_LONG).show();
} catch (Exception ex) {
ex.printStackTrace();
System.out.print("OOPS!");
}
}
}
your request code is unique and this is your problem. you must use unique code for your different alarms. your code with one request code override alarm time. (sorry for my bad english, it is not my language!)
use this code:
for (int i = 0; i < length; i++) {
.
.
.
int requestCode = (int) (System.currentTimeMillis());
PendingIntent pendingIntent = PendingIntent.getActivity(this,
requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Thread.sleep(10);
.
.
.
}
If you want 5 different alarms then your PendingIntent should be different. You can make a PendingIntent unique by putting an extra in it. but anyway, your code should at least generate one alarm. Verify that the time you are setting in the calendar is correct.
Anyway, you don't need 5 separate calendars, intents or anything. just update them and set the alarm. you definitively don't need to save them in an array.