I'm making an application that lets the user choose days and start an alarm on a specific time on those days.
lets take my problem as an example I want my alarm to fire every Friday at 12:30
the problem is It just never fires the alarm even though I'm in the same day here is my code
cals = Calendar.getInstance();
int days = Calendar.FRIDAY + (7 - cals.get(Calendar.DAY_OF_WEEK)); // how many days until Sunday
cals.add(Calendar.DATE, days);
cals.set(Calendar.DAY_OF_WEEK,6);
cals.set(Calendar.HOUR_OF_DAY, 12);
cals.set(Calendar.MINUTE, 30);
cals.set(Calendar.SECOND, 0);
cals.set(Calendar.MILLISECOND, 0);
alarm.SetAlarm(getApplicationContext(), 10,"Start", cals.getTimeInMillis());
public void SetAlarm(Context context,int id,String sor,long time)
{
AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
if(sor.equals("Start"))
{
Intent i = new Intent(context, MyAppReceiver.class);
PendingIntent p = PendingIntent.getBroadcast(context, 0, i, 0);
am.setRepeating(AlarmManager.RTC_WAKEUP, time, DateUtils.DAY_IN_MILLIS, p);
}
}
Did you register your MyAppReceiver as a BroadcastReceiver in the AndroidManifest.xml?
Related
I'm currently trying to make an alarm app that will mute all audio volume at the user-defined day and time. However, the alarm seems not fired at the correct time. I found that the alarm is always fired earlier.
This is my set alarm code:
public static void setAlarm(Context context, String time, int day, int reqCode) {
String[] timeSplit = time.split(":");
Calendar calendar = Calendar.getInstance();
int hour = Integer.parseInt(timeSplit[0]);
int minute = Integer.parseInt(timeSplit[1]);
int days = (day-calendar.get(Calendar.DAY_OF_WEEK) + calendar.get(Calendar.DAY_OF_MONTH));
calendar.set(
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
days,
hour,
minute,
0
);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, RuleAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, reqCode, intent, 0);
// Set the alarm to be fired every week on the selected day
alarmManager.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), 7 * 24 * 60 * 60 * 1000, pendingIntent);
Toast.makeText(context, "Alarm is set", Toast.LENGTH_SHORT).show();
}
I have tried to change setRepeating() to setInexactRepeating() but nothing changed.
AlarmManger is inexact to save battery by combining wakeup calls.
https://developer.android.com/reference/android/app/AlarmManager.html
Try this
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 7 * 24 * 60 * 60 * 1000, pendingIntent);
The problem is that if you are creating PendingIntent for an alarm for past time it will be fired immediately.If you would like to prevent that happening, then simply do not set alarms with a past trigger time . Use BroadcastReceiver for receiving alarm.
Update :
Check we aren't setting it in the past which would trigger it to fire instantly
if(calendar.getTimeInMillis() < System.currentTimeMillis()) {
calendar.add(Calendar.DAY_OF_YEAR, 7);
}
I finally find out the problem. It lies on the day params. What I pass to day params is my Spinner selected position which starts from zero while the Calendar days starts from one (SUNDAY = 1, MONDAY = 2, so on). So, the alarm will always be set in the past days. I plus one to the day params and it's worked.
This is my piece of code where the startAlarm() function got called.
String ruleStartTime = rule_startTime.getText().toString();
// Spinner index starts from zero,
// to match with the Calendar day indexing, we need to plus it one
int dayIdx = day.getSelectedItemPosition()+1;
Alarm.setAlarm(getApplicationContext(), ruleStartTime,
dayIdx, 0);
Below is the code I am using to create alarms when data is pulled from external API. If the time set is in the past, the alarm goes off as soon as it is set(2 second gap). For example if I set the alarm for 8:00 AM, 10th April at 10:00 AM on 11th April(Past time). It starts the alarm as soon as it is set.
public static final int ALARM_REQUEST_CODE = 1001;
public static AlarmManager alarmManager = (AlarmManager) EHCApplication.getInstance().getApplicationContext().getSystemService(Context.ALARM_SERVICE);
public static Intent alarmIntent = new Intent(EHCApplication.getInstance().getApplicationContext(), AlarmReceiver.class);
public static PendingIntent pendingIntent = PendingIntent.getBroadcast(EHCApplication.getInstance().getApplicationContext(), ALARM_REQUEST_CODE, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
public static void setAlarm(Reminder rm) {
for (ScheduledTime time : rm.getScheduledTime()) {
Bundle bundle = new Bundle();
bundle.putParcelable(Constants.ARGS_SELECTED_MEDICINE, medicine);
alarmIntent.putExtras(bundle);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, time.getTimeInMilliseconds(), AlarmManager.INTERVAL_DAY, pendingIntent);
}
}
I am expecting the alarm to go off from next time it hit the time. Where am I making mistake?
This is the expected behavior.
From the documentation of setRepeating() (and other AlarmManager set methods):
If the stated trigger time is in the past, the alarm will be triggered
immediately
If you would like to prevent that happening, then simply do not set alarms with a past trigger time (e.g. check against System.currentTimeMillis() when setting the alarm).
Well, I ran into same problem and after studying I found that alarm will be run as soon when past time is set for the alarm.
Source: Here is documentation of Alarm Manager - setRepeating()
So, I resolved the issue by checking if "Calendar time is in past from system time than I add a day"
Working code:
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, min);
calendar.set(Calendar.SECOND, 0);
alarmManager.cancel(pendingIntent);
// Check if the Calendar time is in the past
if (calendar.getTimeInMillis() < System.currentTimeMillis()) {
Log.e("setAlarm","time is in past");
calendar.add(Calendar.DAY_OF_YEAR, 1); // it will tell to run to next day
}
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, id, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent); //Repeat every 24 hours
I am setting alarm usng this
Calendar now = Calendar.getInstance();
Calendar alarm = Calendar.getInstance();
alarm.set(Calendar.HOUR_OF_DAY,21);
alarm.set(Calendar.MINUTE,30);
if (alarm.before(now)) {
alarm.add(Calendar.DAY_OF_MONTH, 1); //Add 1 day if time selected before now
}
AlarmManager alarmManager =(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context,Receiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context,(int)alarm.getTimeInMillis(),i,0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, (int)alarm.getTimeInMillis(),AlarmManager.INTERVAL_DAY,pi);
But even if I schedule it for next day,it triggers immediately after saving alarm.
Dont know what the issue is have searched a lot but everyone else gets it working
You are casting a long timestamp to int thus losing bits and changing the actual timestamp value. You end up with a time that already has passed so it executes the intent immediately.
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alarm.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
Notice that I removed the (int) cast in the last line.
I want to do a specific task each week .
So I used an Alarm Manager
when user click button alarmManager running
blow code Works properly:
public void set_alarm(int reapte)
{
Context context=getBaseContext();
Calendar calendar=Calendar.getInstance();
// calendar.set(Calendar.HOUR_OF_DAY, 20); // For 1 PM or 2 PM
//calendar.set(Calendar.MINUTE, 41);
Intent intent= new Intent(context, MyService.class);
intent.putExtra("size", reapte);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pi = PendingIntent.getService(context, 0,
intent ,PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY*7, pi);
}
The problem that I have.
When the user clicks. Alarm Manager runs the same moment.
And next week will run.
I want to first run the alarm from next week
.sorry My language is not good
Try this
you can set the day from which alarm will begin.
calendar.set(Calendar.DAY_OF_WEEK, 1);
where sunday=1 and so on to sat=7
and set the time 2 min before from current time when alarm was set,so it will same day of next week
I finally find the answer
WEEK_OF_MONTH values is between 1 and 4.
so
I use below code:
int week=calendar.get(Calendar.WEEK_OF_MONTH);
int day=calendar.get(Calendar.DAY_OF_WEEK);
int hour=calendar.get(Calendar.WEEK_OF_YEAR);
int minute= calendar.get(Calendar.MINUTE);
calendar.set(Calendar.DAY_OF_WEEK, day);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE,minute);
int next_week=week+1;
if(next_week>4)
next_week=1;
calendar.set(Calendar.WEEK_OF_MONTH, next_week);
//other code
I've searched for examples of how to implement such a problem but couldn't find anything that could solve my problem so I'm asking you for an advice how to solve it.
I have to implement an alarm that fires every day at a specific time during the period between two specified dates.
Up to now I have a repeating alarm firing every day at a specific time but not specified until when to repeat...
Any advice and ideas will be highly appreciated!
Suppose you want to set an repeating Alarm from Date1 to Date2.
For Date1, there is no problem for you since it is working.
Set an alarm for Date2 and when that alarm is fired cancel Date1 repeating alarm.
I do it like this:
Lets say you wanted to set a repeating alarm, that first triggered at a 'random' time between two hours (e.g. 0100 - 0500) in the day, and then always triggered at that same time of day again every 24 hours.
private long getTimeOfNextWidgetAutoUpdateInMilliseconds(Calendar now, int startHour, int endHour){
// calc the time diff in milliseconds from now until a 'random' time between startHour and endHour
// ensure to +1 day if the time has already passed
}
private void createAutoRefreshAlarm(Context context, long initialTriggerTimeInMillis,
long intervalInMillis) {
AlarmManager alarmManager = getAlarmManager(context);
PendingIntent widgetRefreshPi = getWidgetRefreshAlarmPendingIntent(context);
setRepeatingAlarm(initialTriggerTimeInMillis, intervalInMillis, widgetRefreshPi,
alarmManager);
ApplicationData.setAppDataBoolean(WIDGET_REFRESH_ALARM_SERVICE_INITITATED, true);
}
private static void setRepeatingAlarm(long initialTriggerTimeInMillis, long intervalInMillis,
PendingIntent widgetRefreshPi, AlarmManager alarmManager) {
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
initialTriggerTimeInMillis,
intervalInMillis,
widgetRefreshPi);
}
private PendingIntent getWidgetRefreshAlarmPendingIntent(Context context) {
Intent alarmIntent = new Intent(context, AlarmManagerBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
private static AlarmManager getAlarmManager(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
return alarmManager;
}
I would then have the following in the WidgetProvider class:
#Override
public void onEnabled(Context context) {
super.onEnabled(context);
int startHour = 1;
int endHour = 5;
long initialTriggerTimeInMillis = getTimeOfNextWidgetAutoUpdateInMilliseconds(
Calendar.getInstance(),
startHour,
endHour);
long intervalInMillis = 86400000; // 24 hours
createAutoRefreshAlarm(context, initialTriggerTimeInMillis, intervalInMillis);
}
This should get you going, I've cut+pasted from my own project, so there may be a few errors.
Also, remember to cancel your alram in the onDisabled() method of your `WidgetProvider.
There are other scenarios that delete the alarm that you should consider, e.g. ON BOOT