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.
Related
First I want to change textview text everyday automatically. For example, first day the textview text is "First text", and second day text is "Second text" at 8 o'clock eveyday. And the text is permanent until next day 8 o'clock.
I try this code but my problem is that the code is not triggered if the user doesn't open this page at 8 o'clock. Texts are inside "mquote array"
SharedPreferences pref =getApplicationContext().getSharedPreferences("myPrefsKey",Context.MODE_PRIVATE) ;
dayCount = pref.getInt("dayCount", 0);
Calendar cal = Calendar.getInstance();
int hour=cal.get(Calendar.HOUR_OF_DAY);
int minute=cal.get(Calendar.MINUTE);
if ((hour==8 && minute==1 ))
updateQuote();
tvQuote.setText(mquote.getQuote(dayCount));
public void updateQuote()
{
if (dayCount==4)
dayCount=0;
dayCount++;
pref.edit().putInt("dayCount",dayCount).apply();
}
You need an AlarmManager implementation:
public class AlarmReceiver extends BroadcastReceiver {
// The app's AlarmManager, which provides access to the system alarm services.
private AlarmManager alarmMgr;
// The pending intent that is triggered when the alarm fires.
private PendingIntent alarmIntent;
public void setAlarm(Context context) {
alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
// set the Alarm's trigger time to 8:00 a.m.
calendar.set(Calendar.HOUR_OF_DAT, 9);
// Set the alarm to fire at approximately 8:30 a.m., according to the device's
// clock, and to repeat once a day.
alarmManager.setInexactRepeating(AlarmManager.RTC,
calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, alarmIntent);
}
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))
{
alarm.setAlarm(context);
} else if(Objects.equals(intent, alarmIntent)) {
SharedPreferences pref = getApplicationContext().getSharedPreferences("key", Context.MODE_PRIVATE);
int dayCount = pref.getInt("dayCount", 0);
dayCount %= 4;
pref.edit().putInt("dayCount", ++daysCount).apply();
}
}
}
You should use timestamp to be able to compare two dates. try this code.
But the 1 day happens while user is using the app, it will not trigger. If you want to overcome this, then use AlarmManager to trigger an event every single day.
SharedPreferences pref = getApplicationContext().getSharedPreferences("myPrefsKey",Context.MODE_PRIVATE);
lastDay_ms= pref.getInt("time_ms", 0);
Calendar today = Calendar.getInstance();
long diff = today.getTimeInMillis() - lastDay_ms; //result in millis
final long ONE_DAY = 24*60*60*1000; //millis in a day
if (diff > ONE_DAY)
updateQuote();
Store milliseconds when you last updated preferences in your preferences:
SharedPreferences pref = getApplicationContext().getSharedPreferences("msKey", Context.MODE_PRIVATE);
msCount = pref.getInt("msCount", 0);
long milliseconds = System.currentTimeMillis();
long diff = milliseconds - msCount;
diff += (8 * 60 * 60 * 1000); // compensating difference for 8'O clock condition
int days = (int) Math.ceil(diff / 24 / 60 / 60 / 1000);
days %= 4; // Because you were resetting days count after 4 increments
updateQuote(days);
public void updateQuote(days) {
if(days == 0) {
pref.edit().putInt("msCount", milliseconds).apply();
}
}
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.
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 build an Activity that user could select the days they want
such as Sun, Mon, Tue, wed,...,Sat
and a method in the Activity is use to set the time user choose
if(action) { //10分鐘該一次
PendingIntent sender = PendingIntent.getBroadcast(MedicationAddRemineActivity.this ,
0 , intent, 0 );
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP
, fireTime, 10*60*1000, sender);
} else { //關閉鬧鐘
PendingIntent cancelSecder = PendingIntent.getBroadcast(MedicationAddRemineActivity.this ,
0 , intent, 0);
alarm.cancel(cancelSecder);
}
But I want to build a function to handle user selected days every week by the radioButton.
If the user selected Monday and Friday, device should show a dialog to user
every Monday and Friday, until it be canceled.
How do I build the function?
Count the AlarmManager start time:
long totalTime = 0;
if(moon.equals("下午")) {
totalTime = total + 12*3600;
} else {totalTime = total + 0;}
//取得系統當時時間
Time t = new Time();
int sysHour = t.hour;
int sysMin = t.minute;
int sysSecond = t.second;
long sysTotal = sysHour*3600 + sysMin*60 +sysSecond;
//處理用藥提醒時間
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
long transfer = Long.parseLong(format.format(totalTime));
String transferdTime = String.valueOf(sysTotal - transfer);
return transferdTime;
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.