I have an AlarmManager that I call at the end of every day, ie 23.59PM, to do some stuff for the new day. (Its called, NewDayReceiver.class.) It repeats every day.
I also set a broadcast receiver that will run the alarm on reboot. It all works fine.
However, if the phone is off at the end of the day, the alarm for that day is not called. When the phone is turned back on, on boot the alarm is set again, however its set for the end of the new day. It comes out, that the alarm for that day was never called. For example, if its off Sunday night, on Monday morning the phone is turned on but the alarm hasn't been called. It will only be called Monday night?
How can I do it, that on the boot broadcast receiver, I can check if the alarm was called for that day, and if it wasn't set the alarm to go off right away.
I hope its clear.
Here is my alarm for every day.
Intent intent = new Intent(this, NewDayReceiver.class);
AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
if(!calendar.before(Calendar.getInstance())) {
// Repeat every 24 hours
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24*60*60*1000, pendingIntent);
Log.d(TAG, "New day alarm set for:" + calendar.getTime() + " and will repeat every day");
}
Here is my BroadcastReceiver, that I call on boot:
public class BootBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "999.BootBroadcastReceiver";
#Override
public void onReceive(Context pContext, Intent intent) {
newDayAlarm(pContext);
newWeekAlarm(pContext);
}
private void newWeekAlarm(Context context) {
Intent intent = new Intent(context, NewWeekReceiver.class);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 55, intent, 0);
// real for end of week
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
calendar.set(Calendar.HOUR_OF_DAY, 23);
calendar.set(Calendar.MINUTE, 59);
calendar.set(Calendar.SECOND, 59);
if(!calendar.before(Calendar.getInstance())) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Log.d(TAG, "New week alarm set for:" + calendar.getTime());
}
}
}
Related
I want the AlarmManager to set an alarm at 2 am daily... So below setAlarm is called only the first time someone opens the apps. I have added alarmManager.setRepeating so that it occurs daily.
public class AlarmUtil {
public static void setAlarm(Context context) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
if (alarmManager != null) {
long start = System.currentTimeMillis();
Intent in = new Intent("ALARM_RECEIVER");
PendingIntent pi = PendingIntent.getBroadcast(context, 0, in, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.HOUR, 2);
calendar.set(Calendar.AM_PM, Calendar.AM);
DateFormat format = new SimpleDateFormat("MMMM dd , yyyy HH:mm:ss", Locale.ENGLISH);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
}
}
}
The below class is what should get called at 2 am daily irrespective of whether app is active or inactive.
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, AlarmService.class));
}
But my problem is the above AlarmReceiver gets called every 30 seconds or somewhat occurs randomly, but occurs many times, whereas I want it just to get called once a day. I don't understand where am I going wrong?
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 have an alarm in my app:
public class MainActivity extends AppCompatActivity {
#Override
public void onCreate(Bundle savedInstanceState){
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.curentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(MINUTE, 11);
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = Pending.getBroadcast(this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntente);
}
}
This is my AlarmReceiver.class
public class AlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent){
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println("ALARM: " + sdf.format(new Date()));
}
}
And in my AndroidManifest.xml I have this line
<receiver android:name=".main.AlarmReceiver" />
The issue is that the alarm does not alarm for the time I set. I set the alarm for
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(MINUTE, 5);
Then the alarm alarmed at 11:11:29. Then I set the alarm for
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(MINUTE, 20);
Then the alarm alarmed at 11:26:29. Then I set the alarm for
calendar.set(Calendar.HOUR_OF_DAY, 11);
calendar.set(MINUTE, 29);
Then the alarm alarmed at 11:41:29.
It continued this way all morning. However, if I replace this line
alarmManager.setInexactRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntente);
with this line
alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, (SystemClock.elapsedRealtime()+10000), pendingIntent);
Then the alarm alarms perfectly in the appropriate 10 seconds.
What is going on?
As per the documentation, setInexactRepeating is not accurate by design. In order to reduce the battery drain by waking up the device too many times, it internally tries to fire several alarms at the same time resulting in inexact alarm time for some of the clients.
https://developer.android.com/reference/android/app/AlarmManager.html#setInexactRepeating(int,%20long,%20long,%20android.app.PendingIntent)
I am setting Alarm using Alarm Manager And setting this Alarm By Picking Values from SQlite Database.The Alarm is working fine for future Alarms but the problem is when I open the Activity in which Alarm Function is Called, The Alarm Start ringing for All Previous Times. How Should I solve this problem ?
Here is My Alarm Function
void Alaramset()
{
Cursor cursor=mydb.getAllData();
if (cursor.moveToFirst())
{
do{
String alarm1 = cursor.getString (cursor.getColumnIndex(DBHelper.ALARM_COLUMN_REMINDER1));
int id = Integer.parseInt(cursor.getString(cursor.getColumnIndex(DBHelper.ALARM_COLUMN_ID)));
int minute=Integer.parseInt (alarm1.substring(3, 5));
int hr=Integer.parseInt(alarm1.substring(0, 2));
Intent myIntent = new Intent(getActivity(), MyAlaramService.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
PendingIntent pendingIntent = PendingIntent.getService(getActivity(), id, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager)getActivity().getSystemService(Context.ALARM_SERVICE);
// Toast.makeText(getActivity(), ""+minute+" : "+hr, 300).show();
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, hr);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
while (cursor.moveToNext());
}
}
It looks like you are scheduling alarms that happen in the past.
Any alarm scheduled in the past will trigger immediately.
A simple solution would be to schedule past alarms for the next day.
Calendar now = Calendar.getInstance();
now.setTimeInMillis(System.currentTimeMillis());
if (calendar.before(now) {
// alarm has already happened. schedule it for tomorrow
calendar.add(Calendar.Date, 1);
}
alarmManager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
I would like to set a notification at 8th of every month.
This is what i did:
Intent myIntent = new Intent(remember.this, receiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(remember.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
// Set the alarm to start at approximately 8th of
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.DAY_OF_MONTH, 8);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY*30, pendingIntent);
However what i got was a constant notification within minutes. And this does not go away.
Would appreciate your help here as i really do not know where went wrong.
Set calendar to upcoming 8th of the month.
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis() , pendingIntent);
Inside receiver.class
public void onReceive(Context context, Intent intent) {
//do action needed
//invoke alarmManager in mainActivity
// cancel the previous alarm
// set the new alarm for the next month
}