Search code examples
javaandroiddatealarmmanager

Updating widget at midnight (12 AM) fails


I have a Hijri calendar app with a widget. The date of the Hijri calendar should change at midnight using the AlarmManager. The problem is that in spite of using Alarm Manager to schedule the midnight update, the widget doesn't update exactly at 12 midnight. It will update somewhere between 12 and 1 AM.

Where am I going wrong?

Java:

private static PendingIntent service = null;
private static long UPDATES_CHECK_INTERVAL = 24 * 60 * 60 * 1000;


    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
    {

        schedule(context);
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }


    protected void schedule(Context context) {
        final AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

        final Calendar TIME = Calendar.getInstance();
        Date now = new Date();
        TIME.add(Calendar.DAY_OF_MONTH, 1);
        TIME.set(Calendar.HOUR_OF_DAY, 0);
        TIME.set(Calendar.MINUTE, 0);
        TIME.set(Calendar.SECOND, 0);
        TIME.set(Calendar.MILLISECOND, 0);

        long firstTime = (TIME.getTimeInMillis()-now.getTime());

        final Intent i = new Intent(context, UpdateService.class);

        if (service == null)
        {
            service = PendingIntent.getService(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);
        }

        m.setRepeating(AlarmManager.RTC, firstTime, UPDATES_CHECK_INTERVAL, service);
    }

Manifest:

<receiver android:name="com.example.app.Widget" android:label="Calendar" android:exported="false">
    <intent-filter >
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        <action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
        <action android:name="android.intent.action.TIMEZONE_CHANGED" />
        <action android:name="android.intent.action.TIME_SET" />
        <action android:name="android.intent.action.DATE_CHANGED" />
    </intent-filter>

    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/widget_info" />
</receiver>

Solution

  • I think you need to change the code related to Calender and AlarmManager.

    This calender represents the exact time of next day's midnight. and the AlarmManager will fire the intent at that time each day.

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.HOUR, 0);
    calendar.set(Calendar.AM_PM, Calendar.AM);
    calendar.add(Calendar.DAY_OF_MONTH, 1); 
    
    AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, service);
    

    Note: I think you should add the above code in the onEnabled() method. Here is a highlight of the AppWidgetProvider's related methods.