androidandroid-intentandroid-pendingintentandroid-alarmsrepeatingalarm

Receiving Alarm Intent Multiple Times


I need my alarm to fire once every day at 11am, and update all of my widgets. When I'm testing my application with one widget, my onReceive() method fires multiple times once the time arrives, updating my widget every time. Why does this happen?

This is my code:

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    theAppWidgetManager = appWidgetManager;
    // There may be multiple widgets active, so update all of them
    for (int appWidgetId : appWidgetIds) {
        ...
    }
    scheduleNextUpdate(context);
}

@Override
public void onReceive(Context context, Intent intent){
    if (intent.getAction().equals(ACTION_SCHEDULED_UPDATE)) {
        AppWidgetManager manager = AppWidgetManager.getInstance(context);
        int[] ids = manager.getAppWidgetIds(new ComponentName(context, AppWidget.class));
        onUpdate(context, manager, ids);
    }
    super.onReceive(context, intent);

}
private  void scheduleNextUpdate(Context context) {
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context, AppWidget.class);
    intent.setAction(ACTION_SCHEDULED_UPDATE);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

    // Get a calendar instance for midnight tomorrow.
    Calendar at11 = Calendar.getInstance();
    at11.set(Calendar.HOUR_OF_DAY, 11);
    at11.set(Calendar.MINUTE, 30);
    at11.set(Calendar.SECOND, 1);
    at11.set(Calendar.MILLISECOND, 0);
    at11.add(Calendar.DAY_OF_YEAR, 1);

    // For API 19 and later, set may fire the intent a little later to save battery,
    // setExact ensures the intent goes off exactly at midnight.
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        alarmManager.set(AlarmManager.RTC_WAKEUP, at11.getTimeInMillis(), pendingIntent);
    } else {
        alarmManager.setExact(AlarmManager.RTC_WAKEUP, at11.getTimeInMillis(), pendingIntent);
    }
}

Solution

  • I think that the problem here is that you're scheduling next updates in onUpdate method. Description of this method says, that:

    Called in response to the AppWidgetManager.ACTION_APPWIDGET_UPDATE and AppWidgetManager.ACTION_APPWIDGET_RESTORED broadcasts when this AppWidget provider is being asked to provide RemoteViews for a set of AppWidgets.

    so, in theory it could trigger several times. I think you should, either schedule next updates in onReceive, or check, somehow, if the broadcast for next update is already scheduled.