Home | History | Annotate | Download | only in app
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package androidx.core.app;
     18 
     19 import android.app.AlarmManager;
     20 import android.app.PendingIntent;
     21 import android.os.Build;
     22 
     23 import androidx.annotation.NonNull;
     24 
     25 /**
     26  * Compatibility library for {@link AlarmManager} with fallbacks for older platforms.
     27  */
     28 public final class AlarmManagerCompat {
     29     /**
     30      * Schedule an alarm that represents an alarm clock.
     31      *
     32      * The system may choose to display information about this alarm to the user.
     33      *
     34      * <p>
     35      * This method is like {@link #setExact}, but implies
     36      * {@link AlarmManager#RTC_WAKEUP}.
     37      *
     38      * @param alarmManager AlarmManager instance used to set the alarm
     39      * @param triggerTime time at which the underlying alarm is triggered in wall time
     40      *                    milliseconds since the epoch
     41      * @param showIntent an intent that can be used to show or edit details of
     42      *                    the alarm clock.
     43      * @param operation Action to perform when the alarm goes off;
     44      *        typically comes from {@link PendingIntent#getBroadcast
     45      *        IntentSender.getBroadcast()}.
     46      *
     47      * @see AlarmManager#set
     48      * @see AlarmManager#setRepeating
     49      * @see AlarmManager#setWindow
     50      * @see #setExact
     51      * @see AlarmManager#cancel
     52      * @see AlarmManager#getNextAlarmClock()
     53      * @see android.content.Context#sendBroadcast
     54      * @see android.content.Context#registerReceiver
     55      * @see android.content.Intent#filterEquals
     56      */
     57     public static void setAlarmClock(@NonNull AlarmManager alarmManager, long triggerTime,
     58             @NonNull PendingIntent showIntent, @NonNull PendingIntent operation) {
     59         if (Build.VERSION.SDK_INT >= 21) {
     60             alarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(triggerTime, showIntent),
     61                     operation);
     62         } else {
     63             AlarmManagerCompat.setExact(alarmManager, AlarmManager.RTC_WAKEUP, triggerTime,
     64                     operation);
     65         }
     66     }
     67 
     68     /**
     69      * Like {@link AlarmManager#set(int, long, PendingIntent)}, but this alarm will be allowed to
     70      * execute even when the system is in low-power idle modes.  This type of alarm must <b>only</b>
     71      * be used for situations where it is actually required that the alarm go off while in
     72      * idle -- a reasonable example would be for a calendar notification that should make a
     73      * sound so the user is aware of it.  When the alarm is dispatched, the app will also be
     74      * added to the system's temporary whitelist for approximately 10 seconds to allow that
     75      * application to acquire further wake locks in which to complete its work.</p>
     76      *
     77      * <p>These alarms can significantly impact the power use
     78      * of the device when idle (and thus cause significant battery blame to the app scheduling
     79      * them), so they should be used with care.  To reduce abuse, there are restrictions on how
     80      * frequently these alarms will go off for a particular application.
     81      * Under normal system operation, it will not dispatch these
     82      * alarms more than about every minute (at which point every such pending alarm is
     83      * dispatched); when in low-power idle modes this duration may be significantly longer,
     84      * such as 15 minutes.</p>
     85      *
     86      * <p>Unlike other alarms, the system is free to reschedule this type of alarm to happen
     87      * out of order with any other alarms, even those from the same app.  This will clearly happen
     88      * when the device is idle (since this alarm can go off while idle, when any other alarms
     89      * from the app will be held until later), but may also happen even when not idle.</p>
     90      *
     91      * <p>Regardless of the app's target SDK version, this call always allows batching of the
     92      * alarm.</p>
     93      *
     94      * @param alarmManager AlarmManager instance used to set the alarm
     95      * @param type One of {@link AlarmManager#ELAPSED_REALTIME},
     96      *        {@link AlarmManager#ELAPSED_REALTIME_WAKEUP},
     97      *        {@link AlarmManager#RTC}, or {@link AlarmManager#RTC_WAKEUP}.
     98      * @param triggerAtMillis time in milliseconds that the alarm should go
     99      * off, using the appropriate clock (depending on the alarm type).
    100      * @param operation Action to perform when the alarm goes off;
    101      * typically comes from {@link PendingIntent#getBroadcast
    102      * IntentSender.getBroadcast()}.
    103      *
    104      * @see AlarmManager#set(int, long, PendingIntent)
    105      * @see #setExactAndAllowWhileIdle
    106      * @see AlarmManager#cancel
    107      * @see android.content.Context#sendBroadcast
    108      * @see android.content.Context#registerReceiver
    109      * @see android.content.Intent#filterEquals
    110      * @see AlarmManager#ELAPSED_REALTIME
    111      * @see AlarmManager#ELAPSED_REALTIME_WAKEUP
    112      * @see AlarmManager#RTC
    113      * @see AlarmManager#RTC_WAKEUP
    114      */
    115     public static void setAndAllowWhileIdle(@NonNull AlarmManager alarmManager, int type,
    116             long triggerAtMillis, @NonNull PendingIntent operation) {
    117         if (Build.VERSION.SDK_INT >= 23) {
    118             alarmManager.setAndAllowWhileIdle(type, triggerAtMillis, operation);
    119         } else {
    120             alarmManager.set(type, triggerAtMillis, operation);
    121         }
    122     }
    123 
    124     /**
    125      * Schedule an alarm to be delivered precisely at the stated time.
    126      *
    127      * <p>
    128      * This method is like {@link AlarmManager#set(int, long, PendingIntent)}, but does not permit
    129      * the OS to adjust the delivery time.  The alarm will be delivered as nearly as
    130      * possible to the requested trigger time.
    131      *
    132      * <p>
    133      * <b>Note:</b> only alarms for which there is a strong demand for exact-time
    134      * delivery (such as an alarm clock ringing at the requested time) should be
    135      * scheduled as exact.  Applications are strongly discouraged from using exact
    136      * alarms unnecessarily as they reduce the OS's ability to minimize battery use.
    137      *
    138      * @param alarmManager AlarmManager instance used to set the alarm
    139      * @param type One of {@link AlarmManager#ELAPSED_REALTIME},
    140      *        {@link AlarmManager#ELAPSED_REALTIME_WAKEUP},
    141      *        {@link AlarmManager#RTC}, or {@link AlarmManager#RTC_WAKEUP}.
    142      * @param triggerAtMillis time in milliseconds that the alarm should go
    143      *        off, using the appropriate clock (depending on the alarm type).
    144      * @param operation Action to perform when the alarm goes off;
    145      *        typically comes from {@link PendingIntent#getBroadcast
    146      *        IntentSender.getBroadcast()}.
    147      *
    148      * @see AlarmManager#set
    149      * @see AlarmManager#setRepeating
    150      * @see AlarmManager#setWindow
    151      * @see AlarmManager#cancel
    152      * @see android.content.Context#sendBroadcast
    153      * @see android.content.Context#registerReceiver
    154      * @see android.content.Intent#filterEquals
    155      * @see AlarmManager#ELAPSED_REALTIME
    156      * @see AlarmManager#ELAPSED_REALTIME_WAKEUP
    157      * @see AlarmManager#RTC
    158      * @see AlarmManager#RTC_WAKEUP
    159      */
    160     public static void setExact(@NonNull AlarmManager alarmManager, int type, long triggerAtMillis,
    161             @NonNull PendingIntent operation) {
    162         if (Build.VERSION.SDK_INT >= 19) {
    163             alarmManager.setExact(type, triggerAtMillis, operation);
    164         } else {
    165             alarmManager.set(type, triggerAtMillis, operation);
    166         }
    167     }
    168 
    169     /**
    170      * Like {@link #setExact}, but this alarm will be allowed to execute
    171      * even when the system is in low-power idle modes.  If you don't need exact scheduling of
    172      * the alarm but still need to execute while idle, consider using
    173      * {@link #setAndAllowWhileIdle}.  This type of alarm must <b>only</b>
    174      * be used for situations where it is actually required that the alarm go off while in
    175      * idle -- a reasonable example would be for a calendar notification that should make a
    176      * sound so the user is aware of it.  When the alarm is dispatched, the app will also be
    177      * added to the system's temporary whitelist for approximately 10 seconds to allow that
    178      * application to acquire further wake locks in which to complete its work.</p>
    179      *
    180      * <p>These alarms can significantly impact the power use
    181      * of the device when idle (and thus cause significant battery blame to the app scheduling
    182      * them), so they should be used with care.  To reduce abuse, there are restrictions on how
    183      * frequently these alarms will go off for a particular application.
    184      * Under normal system operation, it will not dispatch these
    185      * alarms more than about every minute (at which point every such pending alarm is
    186      * dispatched); when in low-power idle modes this duration may be significantly longer,
    187      * such as 15 minutes.</p>
    188      *
    189      * <p>Unlike other alarms, the system is free to reschedule this type of alarm to happen
    190      * out of order with any other alarms, even those from the same app.  This will clearly happen
    191      * when the device is idle (since this alarm can go off while idle, when any other alarms
    192      * from the app will be held until later), but may also happen even when not idle.
    193      * Note that the OS will allow itself more flexibility for scheduling these alarms than
    194      * regular exact alarms, since the application has opted into this behavior.  When the
    195      * device is idle it may take even more liberties with scheduling in order to optimize
    196      * for battery life.</p>
    197      *
    198      * @param alarmManager AlarmManager instance used to set the alarm
    199      * @param type One of {@link AlarmManager#ELAPSED_REALTIME},
    200      *        {@link AlarmManager#ELAPSED_REALTIME_WAKEUP},
    201      *        {@link AlarmManager#RTC}, or {@link AlarmManager#RTC_WAKEUP}.
    202      * @param triggerAtMillis time in milliseconds that the alarm should go
    203      *        off, using the appropriate clock (depending on the alarm type).
    204      * @param operation Action to perform when the alarm goes off;
    205      *        typically comes from {@link PendingIntent#getBroadcast
    206      *        IntentSender.getBroadcast()}.
    207      *
    208      * @see AlarmManager#set
    209      * @see AlarmManager#setRepeating
    210      * @see AlarmManager#setWindow
    211      * @see AlarmManager#cancel
    212      * @see android.content.Context#sendBroadcast
    213      * @see android.content.Context#registerReceiver
    214      * @see android.content.Intent#filterEquals
    215      * @see AlarmManager#ELAPSED_REALTIME
    216      * @see AlarmManager#ELAPSED_REALTIME_WAKEUP
    217      * @see AlarmManager#RTC
    218      * @see AlarmManager#RTC_WAKEUP
    219      */
    220     public static void setExactAndAllowWhileIdle(@NonNull AlarmManager alarmManager, int type,
    221             long triggerAtMillis, @NonNull PendingIntent operation) {
    222         if (Build.VERSION.SDK_INT >= 23) {
    223             alarmManager.setExactAndAllowWhileIdle(type, triggerAtMillis, operation);
    224         } else {
    225             AlarmManagerCompat.setExact(alarmManager, type, triggerAtMillis, operation);
    226         }
    227     }
    228 
    229     private AlarmManagerCompat() {
    230     }
    231 }
    232