Home | History | Annotate | Download | only in scheduling
      1 page.title=Scheduling Repeating Alarms
      2 parent.title=Using Wake Locks
      3 parent.link=index.html
      4 
      5 trainingnavtop=true
      6 
      7 @jd:body
      8 
      9 <div id="tb-wrapper">
     10 <div id="tb">
     11 
     12 <!-- table of contents -->
     13 <h2>This lesson teaches you to</h2>
     14 <ol>
     15   <li><a href="#tradeoffs">Understand the Trade-offs</a></li>
     16   <li><a href="#set">Set a Repeating Alarm</a></li>
     17   <li><a href="#cancel">Cancel an Alarm</a></li>
     18   <li><a href="#boot">Start an Alarm When the Device Boots</a></li>
     19 </ol>
     20 
     21 <h2>Try it out</h2>
     22 
     23 <div class="download-box">
     24   <a href="{@docRoot}shareables/training/Scheduler.zip"
     25 class="button">Download the sample</a>
     26  <p class="filename">Scheduler.zip</p>
     27 </div>
     28 
     29 </div>
     30 </div>
     31 
     32 <a class="notice-developers-video wide" href="http://www.youtube.com/watch?v=yxW29JVXCqc">
     33 <div>
     34     <h3>Video</h3>
     35     <p>The App Clinic: Cricket</p>
     36 </div>
     37 </a>
     38 
     39 <a class="notice-developers-video wide"
     40 href="https://www.youtube.com/playlist?list=PLWz5rJ2EKKc-VJS9WQlj9xM_ygPopZ-Qd">
     41 <div>
     42     <h3>Video</h3>
     43     <p>DevBytes: Efficient Data Transfers</p>
     44 </div>
     45 </a>
     46 
     47 <p>Alarms (based on the {@link android.app.AlarmManager} class) give you a way to perform
     48 time-based operations outside the lifetime of your application.
     49 For example, you could use an alarm to initiate a long-running operation, such
     50 as starting a service once a day to download a weather forecast.</p>
     51 
     52 <p>Alarms have these characteristics:</p>
     53 <ul>
     54 
     55 <li>They let you fire Intents at set times and/or intervals.</li>
     56 
     57 <li>You can use them in conjunction with broadcast receivers to start services and perform
     58 other operations.</li>
     59 
     60 <li>They operate outside of your application, so you can use them to trigger events or
     61 actions even when your app is not running, and even if the device itself is asleep.</li>
     62 
     63 <li>They help you to minimize your app's resource requirements. You can schedule operations
     64 without relying on timers or continuously running background services.</li>
     65 
     66 </ul>
     67 
     68 <p class="note"><strong>Note:</strong> For timing operations that are guaranteed to occur
     69 <em>during</em> the lifetime of your application,
     70 instead consider using the {@link android.os.Handler} class in conjunction with
     71 {@link java.util.Timer} and {@link java.lang.Thread}. This approach gives Android better
     72 control over system resources.</p>
     73 
     74 <h2 id="tradeoffs">Understand the Trade-offs</h2>
     75 
     76 <p>A repeating alarm is a relatively simple mechanism with limited flexibility.
     77 It may
     78 not be the best choice for your app, particularly if you need to trigger network
     79 operations. A poorly designed alarm can cause battery drain and put a significant load on
     80 servers.</p>
     81 
     82 <p>A common scenario for triggering an operation outside the lifetime of your app is
     83 syncing data with a server. This is a case where you might be tempted to use a
     84 repeating alarm. But if you own the server that is hosting your app's
     85 data, using <a href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a> (GCM)
     86 in conjunction with <a href="{@docRoot}training/sync-adapters/index.html">sync adapter</a>
     87 is a better solution than {@link android.app.AlarmManager}. A sync adapter gives you all
     88 the same scheduling options as {@link android.app.AlarmManager}, but it offers
     89 you significantly more flexibility. For example,
     90 a sync could be based on a "new data" message from the server/device (see
     91 <a href="{@docRoot}training/sync-adapters/running-sync-adapter.html">Running a Sync
     92 Adapter</a> for details), the user's activity (or inactivity), the time of day, and so on.
     93 See the linked videos at the top of this page for a detailed discussion of when and how
     94 to use GCM and sync adapter.</p>
     95 
     96 <h3>Best practices</h3>
     97 
     98 <p>Every choice you make in designing your repeating alarm can have consequences in how your
     99 app uses (or abuses) system resources. For example, imagine a popular app that
    100 syncs with a server. If the sync operation is based on clock time and every instance of the
    101 app syncs at 11:00 p.m., the load on the server could result in high latency or even
    102 "denial of service." Follow these best practices in using alarms:</p>
    103 
    104 <ul>
    105 <li>Add randomness (jitter) to any network requests that
    106 trigger as a result of a repeating alarm:
    107 <ul>
    108 <li>Do any local work when the alarm triggers. "Local work" means anything that doesn't
    109 hit a server or require the data from the server.</li>
    110 <li>At the same time, schedule the alarm that contains the network requests to fire at some
    111 random period of time.</li> </ul></li>
    112 
    113 
    114 <li>Keep your alarm frequency to a minimum.</li>
    115 <li>Don't wake up the device unnecessarily (this behavior is determined by the alarm type,
    116 as described in <a href="#type">Choose an alarm type</a>).</li>
    117 <li>Don't make your alarm's trigger time any more precise than it has to be.
    118 
    119 
    120 <p>Use {@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()} instead
    121 of {@link android.app.AlarmManager#setRepeating setRepeating()}.
    122 When you use {@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()},
    123 Android synchronizes repeating alarms from multiple apps and fires
    124 them at the same time. This reduces the total number of times the system must wake the
    125 device, thus reducing drain on the battery. As of Android 4.4
    126 (API Level 19), all repeating alarms are inexact. Note that while
    127 {@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()} is an
    128 improvement over {@link android.app.AlarmManager#setRepeating setRepeating()}, it can
    129 still overwhelm a server if every instance of an app hits the server around the same time.
    130 Therefore, for network requests, add some randomness to your alarms, as discussed above.</p>
    131 </li>
    132 
    133 <li>Avoid basing your alarm on clock time if possible.
    134 
    135 <p>Repeating alarms that are based on a precise trigger time don't scale well.
    136 Use {@link android.app.AlarmManager#ELAPSED_REALTIME} if you can. The different alarm
    137 types are described in more detail in the following section.</p>
    138 
    139 </li>
    140 
    141 </ul>
    142 
    143 
    144 <h2 id="set">Set a Repeating Alarm</h2>
    145 
    146 <p>As described above, repeating alarms are a good choice for scheduling regular events or
    147 data lookups. A repeating alarm has the following characteristics:</p>
    148 
    149 <ul>
    150 <li>A alarm type. For more discussion, see <a href="#type">Choose an alarm type</a>.</li>
    151 <li>A trigger time. If the trigger time you specify is in the past, the alarm triggers
    152 immediately.</li>
    153 <li>The alarm's interval. For example, once a day, every hour, every 5 seconds, and so on.</li>
    154 <li>A pending intent that fires when the alarm is triggered. When you set a second alarm
    155 that uses the same pending intent, it replaces the original alarm.</li>
    156 </ul>
    157 
    158 
    159 <h3 id="type">Choose an alarm type</h3>
    160 
    161 <p>One of the first considerations in using a repeating alarm is what its type should be.</p>
    162 
    163 
    164 <p>There are two general clock types for alarms: "elapsed real time" and "real time clock"
    165 (RTC).
    166 Elapsed real time uses the "time since system boot" as a
    167 reference, and real time clock uses UTC (wall clock) time. This means that
    168 elapsed real time is suited to setting an alarm based on the passage of time (for
    169 example, an alarm that fires every 30 seconds) since it isn't affected by
    170 time zone/locale. The real time clock type is better suited for alarms that are dependent
    171 on current locale.</p>
    172 
    173 <p>Both types have a "wakeup" version, which says to wake up the device's CPU if the
    174 screen is off. This ensures that the alarm will fire at the scheduled time. This is useful
    175 if your app has a time dependency&mdash;for example, if it has a limited window to perform a
    176 particular operation. If you don't use the wakeup version of your alarm type, then
    177 all the repeating alarms will fire when your device is next awake.</p>
    178 
    179 <p>If you simply need your alarm to fire at a particular interval (for example, every half
    180 hour), use one of the elapsed real time types. In general, this is the better choice.</p>
    181 
    182 <p>If you need your alarm to fire at a particular time of day,
    183 then choose one of the clock-based real time clock types. Note, however, that this approach can
    184 have some drawbacks&mdash;the app may not translate well to other locales, and if the user
    185 changes the device's time setting, it could cause unexpected behavior in your app. Using a
    186 real time clock alarm type also does not scale well, as discussed above. We recommend
    187 that you use a "elapsed real time" alarm if you can.</p>
    188 
    189 <p>Here is the list of types:</p>
    190 
    191 <ul>
    192 
    193 <li>{@link android.app.AlarmManager#ELAPSED_REALTIME}&mdash;Fires the pending intent based
    194 on the amount of time since the  device was booted, but doesn't wake up the device. The
    195 elapsed time includes any time during which the device was asleep.</li>
    196 
    197 <li>{@link android.app.AlarmManager#ELAPSED_REALTIME_WAKEUP}&mdash;Wakes up the device and
    198 fires the pending intent after the specified length of time has elapsed since device
    199 boot.</li>
    200 
    201 <li>{@link android.app.AlarmManager#RTC}&mdash;Fires the pending intent
    202 at the specified time but does not wake up the device.</li>
    203 
    204 <li>{@link android.app.AlarmManager#RTC_WAKEUP}&mdash;Wakes up the
    205 device to fire the pending intent at the specified time.</li>
    206 </ul>
    207 
    208 <h4>ELAPSED_REALTIME_WAKEUP examples</h3>
    209 
    210 <p>Here are some examples of using {@link android.app.AlarmManager#ELAPSED_REALTIME_WAKEUP}.
    211 </p>
    212 
    213 <p>Wake up the device to fire the alarm in 30 minutes, and every 30 minutes
    214 after that:</p>
    215 
    216 <pre>
    217 // Hopefully your alarm will have a lower frequency than this!
    218 alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
    219         AlarmManager.INTERVAL_HALF_HOUR,
    220         AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);</pre>
    221 
    222 <p>Wake up the device to fire a one-time (non-repeating) alarm in one minute:</p>
    223 
    224 <pre>private AlarmManager alarmMgr;
    225 private PendingIntent alarmIntent;
    226 ...
    227 alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    228 Intent intent = new Intent(context, AlarmReceiver.class);
    229 alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
    230 
    231 alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
    232         SystemClock.elapsedRealtime() +
    233         60 * 1000, alarmIntent);</pre>
    234 
    235 
    236 <h4>RTC examples</h3>
    237 
    238 <p>Here are some examples of using {@link android.app.AlarmManager#RTC_WAKEUP}.</p>
    239 
    240 <p>Wake up the device to fire the alarm at approximately 2:00 p.m., and repeat once a day
    241 at the same time:</p>
    242 
    243 <pre>// Set the alarm to start at approximately 2:00 p.m.
    244 Calendar calendar = Calendar.getInstance();
    245 calendar.setTimeInMillis(System.currentTimeMillis());
    246 calendar.set(Calendar.HOUR_OF_DAY, 14);
    247 
    248 // With setInexactRepeating(), you have to use one of the AlarmManager interval
    249 // constants--in this case, AlarmManager.INTERVAL_DAY.
    250 alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
    251         AlarmManager.INTERVAL_DAY, alarmIntent);</pre>
    252 
    253 <p>Wake up the device to fire the alarm at precisely 8:30 a.m., and every 20 minutes
    254 thereafter:</p>
    255 
    256 <pre>private AlarmManager alarmMgr;
    257 private PendingIntent alarmIntent;
    258 ...
    259 alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    260 Intent intent = new Intent(context, AlarmReceiver.class);
    261 alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
    262 
    263 // Set the alarm to start at 8:30 a.m.
    264 Calendar calendar = Calendar.getInstance();
    265 calendar.setTimeInMillis(System.currentTimeMillis());
    266 calendar.set(Calendar.HOUR_OF_DAY, 8);
    267 calendar.set(Calendar.MINUTE, 30);
    268 
    269 // setRepeating() lets you specify a precise custom interval--in this case,
    270 // 20 minutes.
    271 alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
    272         1000 * 60 * 20, alarmIntent);</pre>
    273 
    274 <h3>Decide how precise your alarm needs to be</h3>
    275 
    276 <p>As described above, choosing the alarm type is often the first step in creating an alarm.
    277 A further distinction is how precise you need your alarm to be. For most apps,
    278 {@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()} is the right
    279 choice.
    280 When you use this method, Android synchronizes multiple inexact repeating alarms and fires
    281 them at the same time. This reduces the drain on the battery.</p>
    282 
    283 <p>For the rare app that has rigid time requirements&mdash;for example, the alarm needs to
    284 fire precisely at 8:30 a.m., and every hour on the hour
    285 thereafter&mdash;use {@link android.app.AlarmManager#setRepeating setRepeating()}. But you
    286 should avoid using exact alarms if possible.</p>
    287 
    288 <p>With {@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()},
    289 you can't specify a custom interval the way you can with
    290 {@link android.app.AlarmManager#setRepeating setRepeating()}. You have to use one of the
    291 interval constants, such as {@link android.app.AlarmManager#INTERVAL_FIFTEEN_MINUTES},
    292 {@link android.app.AlarmManager#INTERVAL_DAY}, and so on. See {@link android.app.AlarmManager}
    293 for the complete list.
    294 </p>
    295 
    296 <h2 id="cancel">Cancel an Alarm</h2>
    297 
    298 <p>Depending on your app, you may want to include the ability to cancel the alarm.
    299 To cancel an alarm, call {@link android.app.AlarmManager#cancel cancel()} on the Alarm
    300 Manager, passing in the {@link android.app.PendingIntent} you no longer want to fire. For
    301 example:</p>
    302 
    303 <pre>// If the alarm has been set, cancel it.
    304 if (alarmMgr!= null) {
    305     alarmMgr.cancel(alarmIntent);
    306 }</pre>
    307 
    308 <h2 id="boot">Start an Alarm When the Device Boots</h2>
    309 
    310 <p>By default, all alarms are canceled when a device shuts down.
    311 To prevent this from happening, you can design your application
    312 to automatically restart a repeating alarm if the user reboots the device. This ensures
    313 that the {@link android.app.AlarmManager} will continue doing its task without the user
    314 needing to manually restart the alarm.</p>
    315 
    316 
    317 <p>Here are the steps:</p>
    318 <ol>
    319 <li>Set the <a href="{@docRoot}reference/android/Manifest.permission.html#RECEIVE_BOOT_COMPLETED">
    320 {@code RECEIVE_BOOT_COMPLETED}</a> permission in your application's manifest. This allows
    321 your app to receive the
    322 {@link android.content.Intent#ACTION_BOOT_COMPLETED} that is broadcast after the system
    323 finishes booting (this only works if the app has already been launched by the user at least once):
    324 <pre>
    325 &lt;uses-permission android:name=&quot;android.permission.RECEIVE_BOOT_COMPLETED&quot;/&gt;</pre>
    326 </li>
    327 
    328 <li>Implement a {@link android.content.BroadcastReceiver} to receive the broadcast:
    329 <pre>public class SampleBootReceiver extends BroadcastReceiver {
    330 
    331     &#64;Override
    332     public void onReceive(Context context, Intent intent) {
    333         if (intent.getAction().equals(&quot;android.intent.action.BOOT_COMPLETED&quot;)) {
    334             // Set the alarm here.
    335         }
    336     }
    337 }</pre></li>
    338 
    339 <li>Add the receiver to your app's manifest file with an intent filter that filters on
    340 the {@link android.content.Intent#ACTION_BOOT_COMPLETED} action:
    341 
    342 <pre>&lt;receiver android:name=&quot;.SampleBootReceiver&quot;
    343         android:enabled=&quot;false&quot;&gt;
    344     &lt;intent-filter&gt;
    345         &lt;action android:name=&quot;android.intent.action.BOOT_COMPLETED&quot;&gt;&lt;/action&gt;
    346     &lt;/intent-filter&gt;
    347 &lt;/receiver&gt;</pre>
    348 
    349 
    350 <p>Notice that in the manifest, the boot receiver is set to
    351 {@code android:enabled=&quot;false&quot;}. This means that the receiver will not be called
    352 unless the application explicitly enables it. This prevents the boot receiver from being
    353 called unnecessarily. You can enable a receiver (for example, if the user sets an alarm)
    354 as follows:</p>
    355 
    356 <pre>ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    357 PackageManager pm = context.getPackageManager();
    358 
    359 pm.setComponentEnabledSetting(receiver,
    360         PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
    361         PackageManager.DONT_KILL_APP);
    362 </pre>
    363 
    364 <p>Once you enable the receiver this way, it will stay enabled, even if the user reboots
    365 the device. In other words, programmatically enabling the receiver overrides the
    366 manifest setting, even across reboots. The receiver will stay enabled until your app disables it.
    367 You can disable a receiver (for example, if the user cancels an alarm) as follows:</p>
    368 
    369 <pre>ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
    370 PackageManager pm = context.getPackageManager();
    371 
    372 pm.setComponentEnabledSetting(receiver,
    373         PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
    374         PackageManager.DONT_KILL_APP);</pre>
    375 
    376 </li>
    377 </ol>
    378