Search code examples
androidalarmmanagerandroid-broadcastreceiver

Android AlarmManager doesn´t work properly


I´m working with alarm manager on my app and I need some DefaultSharedPreferences value to be reset (set to 0) at 2:00 AM. I have a function on my main activity which is called whenever the app is open:

protected void setUpAlarmManager(){ //To delete the data of each day and pass it to Records database
        AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
        Intent intent  = new Intent(this, AlarmReceiver.class);
        PendingIntent pIntent = PendingIntent.getBroadcast(this, 1, intent,  PendingIntent.FLAG_CANCEL_CURRENT);
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 02);
        calendar.set(Calendar.MINUTE, 00);
        calendar.set(Calendar.SECOND, 00);
        alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY , pIntent); //set repeating every 24 hours
        Log.i("Set", "Alarm set");
    }

And then I use a BroadcastReceiver to reset the values.

package com.javierd.iifym;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.util.Log;

import com.javierd.iifym.sqlite.RecordsDataSource;

//To delete the data of each day and pass it to Records database
public class AlarmReceiver extends android.content.BroadcastReceiver {

    private RecordsDataSource dataSource;
    private Utils utils;

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("Time", "TIMEEEE!!!!");
        SharedPreferences macros = context.getSharedPreferences(context.getPackageName() + "_preferences", Context.MODE_PRIVATE); //As we store data using DefaultSharedPreferences, not SharedPreferences
        SharedPreferences.Editor editor = macros.edit();
        editor.putString("eaten_carbs", "0");
        editor.putString("eaten_proteins", "0");
        editor.putString("eaten_fats", "0");
        editor.apply();
    }
}

The receiver works, the problem is that the AlarmManager works randomly. Although it is supposed to just at 2:00 am, maybe you enter the app at 16:00, save some values, at the next time you enter at 17:30 the values are deleted, or maybe not, it´s something random and I do not understand it.


Solution

  • Such effect is caused by using AlarmManager.setInexectRepeating(int, long, long, PendingIntent) I believe. According to the documentation

    Your alarm's first trigger will not be before the requested time, but it might not occur for almost a full interval after that time.

    When you use this method, Android synchronizes multiple inexact repeating alarms and fires them at the same time. And taking into account that the interval is a day, the alarm might fire at 17:30.

    If the alarm needs to fire exactly at 2:00 am then I'd suggest using AlarmManager.setRepeating(int, long, long, PendingIntent) method instead.

    Please be aware that it's recommended to avoid using exact alarms if possible to reduce the drain on the battery.

    Updated.

    I would suggest check if the trigger time isn't in the past.

    Could you please try

    protected void setUpAlarmManager(){ //To delete the data of each day and pass it to Records database
            AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
            Intent intent  = new Intent(this, AlarmReceiver.class);
            PendingIntent pIntent = PendingIntent.getBroadcast(this, 1, intent,  PendingIntent.FLAG_CANCEL_CURRENT);
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.HOUR_OF_DAY, 2);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            if (Calendar.getInstance().after(calendar)) {
                 calendar.add(Calendar.DAY_OF_MONTH, 1);
            }
            alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY , pIntent); //set repeating every 24 hours
            Log.i("Set", "Alarm set");
        }