All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.robolectric.shadows.ShadowAlarmManager Maven / Gradle / Ivy

package org.robolectric.shadows;

import static android.app.AlarmManager.RTC_WAKEUP;
import static android.os.Build.VERSION_CODES.KITKAT;
import static android.os.Build.VERSION_CODES.LOLLIPOP;
import static android.os.Build.VERSION_CODES.M;
import static android.os.Build.VERSION_CODES.N;

import android.annotation.TargetApi;
import android.app.AlarmManager;
import android.app.AlarmManager.AlarmClockInfo;
import android.app.AlarmManager.OnAlarmListener;
import android.app.PendingIntent;
import android.content.Intent;
import android.os.Handler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TimeZone;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.annotation.Resetter;
import org.robolectric.shadow.api.Shadow;

@SuppressWarnings({"UnusedDeclaration"})
@Implements(AlarmManager.class)
public class ShadowAlarmManager {

  private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getDefault();

  private final List scheduledAlarms = new ArrayList<>();

  @RealObject private AlarmManager realObject;

  @Resetter
  public static void reset() {
    TimeZone.setDefault(DEFAULT_TIMEZONE);
  }

  @Implementation
  protected void setTimeZone(String timeZone) {
    // Do the real check first
    Shadow.directlyOn(realObject, AlarmManager.class).setTimeZone(timeZone);
    // Then do the right side effect
    TimeZone.setDefault(TimeZone.getTimeZone(timeZone));
  }

  @Implementation
  protected void set(int type, long triggerAtTime, PendingIntent operation) {
    internalSet(type, triggerAtTime, 0L, operation, null);
  }

  @Implementation(minSdk = N)
  protected void set(
      int type, long triggerAtTime, String tag, OnAlarmListener listener, Handler targetHandler) {
    internalSet(type, triggerAtTime, listener, targetHandler);
  }

  @Implementation(minSdk = KITKAT)
  protected void setExact(int type, long triggerAtTime, PendingIntent operation) {
    internalSet(type, triggerAtTime, 0L, operation, null);
  }

  @Implementation(minSdk = N)
  protected void setExact(
      int type, long triggerAtTime, String tag, OnAlarmListener listener, Handler targetHandler) {
    internalSet(type, triggerAtTime, listener, targetHandler);
  }

  @Implementation(minSdk = KITKAT)
  protected void setWindow(
      int type, long windowStartMillis, long windowLengthMillis, PendingIntent operation) {
    internalSet(type, windowStartMillis, 0L, operation, null);
  }

  @Implementation(minSdk = N)
  protected void setWindow(
      int type,
      long windowStartMillis,
      long windowLengthMillis,
      String tag,
      OnAlarmListener listener,
      Handler targetHandler) {
    internalSet(type, windowStartMillis, listener, targetHandler);
  }

  @Implementation(minSdk = M)
  protected void setAndAllowWhileIdle(int type, long triggerAtTime, PendingIntent operation) {
    internalSet(type, triggerAtTime, 0L, operation, null);
  }

  @Implementation(minSdk = M)
  protected void setExactAndAllowWhileIdle(int type, long triggerAtTime, PendingIntent operation) {
    internalSet(type, triggerAtTime, 0L, operation, null);
  }

  @Implementation
  protected void setRepeating(
      int type, long triggerAtTime, long interval, PendingIntent operation) {
    internalSet(type, triggerAtTime, interval, operation, null);
  }

  @Implementation
  protected void setInexactRepeating(
      int type, long triggerAtMillis, long intervalMillis, PendingIntent operation) {
    internalSet(type, triggerAtMillis, intervalMillis, operation, null);
  }

  @Implementation(minSdk = LOLLIPOP)
  protected void setAlarmClock(AlarmClockInfo info, PendingIntent operation) {
    internalSet(RTC_WAKEUP, info.getTriggerTime(), 0L, operation, info.getShowIntent());
  }

  @Implementation(minSdk = LOLLIPOP)
  protected AlarmClockInfo getNextAlarmClock() {
    for (ScheduledAlarm scheduledAlarm : scheduledAlarms) {
      AlarmClockInfo alarmClockInfo = scheduledAlarm.getAlarmClockInfo();
      if (alarmClockInfo != null) {
        return alarmClockInfo;
      }
    }
    return null;
  }

  private void internalSet(int type, long triggerAtTime, long interval, PendingIntent operation,
      PendingIntent showIntent) {
    cancel(operation);
    scheduledAlarms.add(new ScheduledAlarm(type, triggerAtTime, interval, operation, showIntent));
    Collections.sort(scheduledAlarms);
  }

  private void internalSet(
      int type, long triggerAtTime, OnAlarmListener listener, Handler handler) {
    cancel(listener);
    scheduledAlarms.add(new ScheduledAlarm(type, triggerAtTime, 0L, listener, handler));
    Collections.sort(scheduledAlarms);
  }

  /**
   * @return the next scheduled alarm after consuming it
   */
  public ScheduledAlarm getNextScheduledAlarm() {
    if (scheduledAlarms.isEmpty()) {
      return null;
    } else {
      return scheduledAlarms.remove(0);
    }
  }

  /**
   * @return the most recently scheduled alarm without consuming it
   */
  public ScheduledAlarm peekNextScheduledAlarm() {
    if (scheduledAlarms.isEmpty()) {
      return null;
    } else {
      return scheduledAlarms.get(0);
    }
  }

  /**
   * @return all scheduled alarms
   */
  public List getScheduledAlarms() {
    return scheduledAlarms;
  }

  @Implementation
  protected void cancel(PendingIntent operation) {
    ShadowPendingIntent shadowPendingIntent = Shadow.extract(operation);
    final Intent toRemove = shadowPendingIntent.getSavedIntent();
    final int requestCode = shadowPendingIntent.getRequestCode();
    for (ScheduledAlarm scheduledAlarm : scheduledAlarms) {
      if (scheduledAlarm.operation != null) {
        ShadowPendingIntent scheduledShadowPendingIntent = Shadow.extract(scheduledAlarm.operation);
        final Intent scheduledIntent = scheduledShadowPendingIntent.getSavedIntent();
        final int scheduledRequestCode = scheduledShadowPendingIntent.getRequestCode();
        if (scheduledIntent.filterEquals(toRemove) && scheduledRequestCode == requestCode) {
          scheduledAlarms.remove(scheduledAlarm);
          break;
        }
      }
    }
  }

  @Implementation(minSdk = N)
  protected void cancel(OnAlarmListener listener) {
    for (ScheduledAlarm scheduledAlarm : scheduledAlarms) {
      if (scheduledAlarm.onAlarmListener != null) {
        if (scheduledAlarm.onAlarmListener.equals(listener)) {
          scheduledAlarms.remove(scheduledAlarm);
          break;
        }
      }
    }
  }

  /**
   * Container object to hold a PendingIntent and parameters describing when to send it.
   */
  public static class ScheduledAlarm implements Comparable {

    public final int type;
    public final long triggerAtTime;
    public final long interval;
    public final PendingIntent operation;

    // A non-null showIntent implies this alarm has a user interface. (i.e. in an alarm clock app)
    public final PendingIntent showIntent;

    public final OnAlarmListener onAlarmListener;
    public final Handler handler;

    public ScheduledAlarm(int type, long triggerAtTime, PendingIntent operation,
        PendingIntent showIntent) {
      this(type, triggerAtTime, 0, operation, showIntent);
    }

    public ScheduledAlarm(int type, long triggerAtTime, long interval, PendingIntent operation,
        PendingIntent showIntent) {
      this(type, triggerAtTime, interval, operation, showIntent, null, null);
    }

    private ScheduledAlarm(
        int type,
        long triggerAtTime,
        long interval,
        OnAlarmListener onAlarmListener,
        Handler handler) {
      this(type, triggerAtTime, interval, null, null, onAlarmListener, handler);
    }

    private ScheduledAlarm(
        int type,
        long triggerAtTime,
        long interval,
        PendingIntent operation,
        PendingIntent showIntent,
        OnAlarmListener onAlarmListener,
        Handler handler) {
      this.type = type;
      this.triggerAtTime = triggerAtTime;
      this.operation = operation;
      this.interval = interval;
      this.showIntent = showIntent;
      this.onAlarmListener = onAlarmListener;
      this.handler = handler;
    }

    @TargetApi(LOLLIPOP)
    public AlarmClockInfo getAlarmClockInfo() {
      return showIntent == null ? null : new AlarmClockInfo(triggerAtTime, showIntent);
    }

    @Override
    public int compareTo(ScheduledAlarm scheduledAlarm) {
      return Long.compare(triggerAtTime, scheduledAlarm.triggerAtTime);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy