1page.title=Scheduling Repeating Alarms 2parent.title=Using Wake Locks 3parent.link=index.html 4 5trainingnavtop=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" 25class="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" 40href="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 48time-based operations outside the lifetime of your application. 49For example, you could use an alarm to initiate a long-running operation, such 50as 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 58other operations.</li> 59 60<li>They operate outside of your application, so you can use them to trigger events or 61actions 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 64without 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, 70instead 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 72control 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. 77It may 78not be the best choice for your app, particularly if you need to trigger network 79operations. A poorly designed alarm can cause battery drain and put a significant load on 80servers.</p> 81 82<p>A common scenario for triggering an operation outside the lifetime of your app is 83syncing data with a server. This is a case where you might be tempted to use a 84repeating alarm. But if you own the server that is hosting your app's 85data, using <a href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a> (GCM) 86in conjunction with <a href="{@docRoot}training/sync-adapters/index.html">sync adapter</a> 87is a better solution than {@link android.app.AlarmManager}. A sync adapter gives you all 88the same scheduling options as {@link android.app.AlarmManager}, but it offers 89you significantly more flexibility. For example, 90a 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 92Adapter</a> for details), the user's activity (or inactivity), the time of day, and so on. 93See the linked videos at the top of this page for a detailed discussion of when and how 94to 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 99app uses (or abuses) system resources. For example, imagine a popular app that 100syncs with a server. If the sync operation is based on clock time and every instance of the 101app 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 106trigger 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 109hit 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 111random 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, 116as 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 121of {@link android.app.AlarmManager#setRepeating setRepeating()}. 122When you use {@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()}, 123Android synchronizes repeating alarms from multiple apps and fires 124them at the same time. This reduces the total number of times the system must wake the 125device, 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 128improvement over {@link android.app.AlarmManager#setRepeating setRepeating()}, it can 129still overwhelm a server if every instance of an app hits the server around the same time. 130Therefore, 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. 136Use {@link android.app.AlarmManager#ELAPSED_REALTIME} if you can. The different alarm 137types 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 147data 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 152immediately.</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 155that 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). 166Elapsed real time uses the "time since system boot" as a 167reference, and real time clock uses UTC (wall clock) time. This means that 168elapsed real time is suited to setting an alarm based on the passage of time (for 169example, an alarm that fires every 30 seconds) since it isn't affected by 170time zone/locale. The real time clock type is better suited for alarms that are dependent 171on current locale.</p> 172 173<p>Both types have a "wakeup" version, which says to wake up the device's CPU if the 174screen is off. This ensures that the alarm will fire at the scheduled time. This is useful 175if your app has a time dependency—for example, if it has a limited window to perform a 176particular operation. If you don't use the wakeup version of your alarm type, then 177all 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 180hour), 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, 183then choose one of the clock-based real time clock types. Note, however, that this approach can 184have some drawbacks—the app may not translate well to other locales, and if the user 185changes the device's time setting, it could cause unexpected behavior in your app. Using a 186real time clock alarm type also does not scale well, as discussed above. We recommend 187that 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}—Fires the pending intent based 194on the amount of time since the device was booted, but doesn't wake up the device. The 195elapsed time includes any time during which the device was asleep.</li> 196 197<li>{@link android.app.AlarmManager#ELAPSED_REALTIME_WAKEUP}—Wakes up the device and 198fires the pending intent after the specified length of time has elapsed since device 199boot.</li> 200 201<li>{@link android.app.AlarmManager#RTC}—Fires the pending intent 202at the specified time but does not wake up the device.</li> 203 204<li>{@link android.app.AlarmManager#RTC_WAKEUP}—Wakes up the 205device 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 214after that:</p> 215 216<pre> 217// Hopefully your alarm will have a lower frequency than this! 218alarmMgr.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; 225private PendingIntent alarmIntent; 226... 227alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); 228Intent intent = new Intent(context, AlarmReceiver.class); 229alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); 230 231alarmMgr.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 241at the same time:</p> 242 243<pre>// Set the alarm to start at approximately 2:00 p.m. 244Calendar calendar = Calendar.getInstance(); 245calendar.setTimeInMillis(System.currentTimeMillis()); 246calendar.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. 250alarmMgr.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 254thereafter:</p> 255 256<pre>private AlarmManager alarmMgr; 257private PendingIntent alarmIntent; 258... 259alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); 260Intent intent = new Intent(context, AlarmReceiver.class); 261alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0); 262 263// Set the alarm to start at 8:30 a.m. 264Calendar calendar = Calendar.getInstance(); 265calendar.setTimeInMillis(System.currentTimeMillis()); 266calendar.set(Calendar.HOUR_OF_DAY, 8); 267calendar.set(Calendar.MINUTE, 30); 268 269// setRepeating() lets you specify a precise custom interval--in this case, 270// 20 minutes. 271alarmMgr.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. 277A further distinction is how precise you need your alarm to be. For most apps, 278{@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()} is the right 279choice. 280When you use this method, Android synchronizes multiple inexact repeating alarms and fires 281them at the same time. This reduces the drain on the battery.</p> 282 283<p>For the rare app that has rigid time requirements—for example, the alarm needs to 284fire precisely at 8:30 a.m., and every hour on the hour 285thereafter—use {@link android.app.AlarmManager#setRepeating setRepeating()}. But you 286should avoid using exact alarms if possible.</p> 287 288<p>With {@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()}, 289you 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 291interval 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} 293for 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. 299To cancel an alarm, call {@link android.app.AlarmManager#cancel cancel()} on the Alarm 300Manager, passing in the {@link android.app.PendingIntent} you no longer want to fire. For 301example:</p> 302 303<pre>// If the alarm has been set, cancel it. 304if (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. 311To prevent this from happening, you can design your application 312to automatically restart a repeating alarm if the user reboots the device. This ensures 313that the {@link android.app.AlarmManager} will continue doing its task without the user 314needing 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 321your app to receive the 322{@link android.content.Intent#ACTION_BOOT_COMPLETED} that is broadcast after the system 323finishes booting (this only works if the app has already been launched by the user at least once): 324<pre> 325<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/></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 @Override 332 public void onReceive(Context context, Intent intent) { 333 if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) { 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 340the {@link android.content.Intent#ACTION_BOOT_COMPLETED} action: 341 342<pre><receiver android:name=".SampleBootReceiver" 343 android:enabled="false"> 344 <intent-filter> 345 <action android:name="android.intent.action.BOOT_COMPLETED"></action> 346 </intent-filter> 347</receiver></pre> 348 349 350<p>Notice that in the manifest, the boot receiver is set to 351{@code android:enabled="false"}. This means that the receiver will not be called 352unless the application explicitly enables it. This prevents the boot receiver from being 353called unnecessarily. You can enable a receiver (for example, if the user sets an alarm) 354as follows:</p> 355 356<pre>ComponentName receiver = new ComponentName(context, SampleBootReceiver.class); 357PackageManager pm = context.getPackageManager(); 358 359pm.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 365the device. In other words, programmatically enabling the receiver overrides the 366manifest setting, even across reboots. The receiver will stay enabled until your app disables it. 367You 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); 370PackageManager pm = context.getPackageManager(); 371 372pm.setComponentEnabledSetting(receiver, 373 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 374 PackageManager.DONT_KILL_APP);</pre> 375 376</li> 377</ol> 378