Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 77364631 authored by Katie McCormick's avatar Katie McCormick Committed by Android Git Automerger
Browse files

am a9fcf662: Merge "New Scheduling class." into jb-mr2-docs

* commit 'a9fcf662':
  New Scheduling class.
parents ab8cabf1 a9fcf662
Loading
Loading
Loading
Loading
+45 KiB

File added.

No diff preview for this file type.

+8 −0
Original line number Diff line number Diff line
page.title=Best Practices for Background Jobs
page.trainingcourse=true

@jd:body


<p>These classes show you how to run jobs in the background to boost your
application's performance and minimize its drain on the battery.</p>
+312 −0
Original line number Diff line number Diff line
page.title=Scheduling Repeating Alarms
parent.title=Using Wake Locks
parent.link=index.html

trainingnavtop=true

@jd:body

<div id="tb-wrapper">
<div id="tb">

<!-- table of contents -->
<h2>This lesson teaches you to</h2>
<ol>
  <li><a href="#set">Set a Repeating Alarm</a></li>
  <li><a href="#cancel">Cancel an Alarm</a></li>
  <li><a href="#boot">Start an Alarm When the Device Boots</a></li>
</ol>

<h2>Try it out</h2>

<div class="download-box">
  <a href="{@docRoot}shareables/training/Scheduler.zip"
class="button">Download the sample</a>
 <p class="filename">Scheduler.zip</p>
</div>

</div>
</div>

<p>Alarms (based on the {@link android.app.AlarmManager} class) give you a way to perform
time-based operations outside the lifetime of your application.
For example, you could use an alarm to initiate a long-running operation, such
as starting a service once a day to download a weather forecast.</p>

<p>Alarms have these characteristics:</p>
<ul>

<li>They let you fire Intents at set times and/or intervals.</li>

<li>You can use them in conjunction with broadcast receivers to start services and perform
other operations.</li>

<li>They operate outside of your application, so you can use them to trigger events or
actions even when your app is not running, and even if the device itself is asleep.</li>

<li>They help you to minimize your app's resource requirements. You can schedule operations
without relying on timers or continuously running background services.</li>

</ul>

<p class="note"><strong>Note:</strong> For timing operations that are guaranteed to occur
<em>during</em> the lifetime of your application,
instead consider using the {@link android.os.Handler} class in conjunction with
{@link java.util.Timer} and {@link java.lang.Thread}. This approach gives Android better
control over system resources.</p>

<h2 id="set">Set a Repeating Alarm</h2>

<p>As described above, repeating alarms are a good choice for scheduling regular events or
data lookups. A repeating alarm has the following characteristics:</p>

<ul>
<li>A alarm type. For more discussion, see <a href="#type">Choose an alarm type</a>.</li>
<li>A trigger time. If the trigger time you specify is in the past, the alarm triggers
immediately.</li>
<li>The alarm's interval. For example, once a day, every hour, every 5 seconds, and so on.</li>
<li>A pending intent that fires when the alarm is triggered. When you set a second alarm
that uses the same pending intent, it replaces the original alarm.</li>
</ul>

<p>Every choice you make in designing your repeating alarm can have consequences in how your
app uses (or abuses) system resources. Even a carefully managed alarm can have a major impact
on battery life. Follow these guidelines as you design your app:</p>

<ul>
<li>Keep your alarm frequency to a minimum.</li>
<li>Don't wake up the device unnecessarily (this behavior is determined by the alarm type,
as described in <a href="#type">Choose an alarm type</a>).</li>
<li>Don't make your alarm's trigger time any more precise than it has to be:

<ul>
<li>Use {@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()} instead
of {@link android.app.AlarmManager#setRepeating setRepeating()} whenever possible.
When you use {@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()},
Android synchronizes multiple inexact repeating alarms and fires
them at the same time. This reduces the drain on the battery.</li>
<li>If your alarm's behavior is based on an interval (for example, your alarm
fires once an hour) rather than a precise trigger time (for example, your alarm fires at
7 a.m. sharp and every 20 minutes after that), use an {@code ELAPSED_REALTIME}
alarm type.</li>
</ul></li>

</ul>

<h3 id="type">Choose an alarm type</h3>

<p>One of the first considerations in using a repeating alarm is what its type should be.</p>


<p>There are two general clock types for alarms: "elapsed real time" and "real time clock"
(RTC).
Elapsed real time uses the "time since system boot" as a
reference, and real time clock uses UTC (wall clock) time. This means that
elapsed real time is suited to setting an alarm based on the passage of time (for
example, an alarm that fires every 30 seconds) since it isn't affected by
time zone/locale. The real time clock type is better suited for alarms that are dependent
on current locale.</p>

<p>Both types have a "wakeup" version, which says to wake up the device's CPU if the
screen is off. This ensures that the alarm will fire at the scheduled time. This is useful
if your app has a time dependency&mdash;for example, if it has a limited window to perform a
particular operation. If you don't use the wakeup version of your alarm type, then
all the repeating alarms will fire when your device is next awake.</p>

<p>If you simply need your alarm to fire at a particular interval (for example, every half
hour), use one of the elapsed real time types. In general, this is the better choice.</p>

<p>If you need your alarm to fire at a particular time of day,
then choose one of the clock-based real time clock types. Note, however, that this approach can
have some drawbacks&mdash;the app may not translate well to other locales, and if the user
changes the device's time setting, it could cause unexpected behavior in your app.</p>

<p>Here is the list of types:</p>

<ul>

<li>{@link android.app.AlarmManager#ELAPSED_REALTIME}&mdash;Fires the pending intent based
on the amount of time since the  device was booted, but doesn't wake up the device. The
elapsed time includes any time during which the device was asleep.</li>

<li>{@link android.app.AlarmManager#ELAPSED_REALTIME_WAKEUP}&mdash;Wakes up the device and
fires the pending intent after the specified length of time has elapsed since device
boot.</li>

<li>{@link android.app.AlarmManager#RTC}&mdash;Fires the pending intent
at the specified time but does not wake up the device.</li>

<li>{@link android.app.AlarmManager#RTC_WAKEUP}&mdash;Wakes up the
device to fire the pending intent at the specified time.</li>
</ul>

<h4>ELAPSED_REALTIME_WAKEUP examples</h3>

<p>Here are some examples of using {@link android.app.AlarmManager#ELAPSED_REALTIME_WAKEUP}.
</p>

<p>Wake up the device to fire the alarm in 30 minutes, and every 30 minutes
after that:</p>

<pre>
// Hopefully your alarm will have a lower frequency than this!
alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
        AlarmManager.INTERVAL_HALF_HOUR,
        AlarmManager.INTERVAL_HALF_HOUR, alarmIntent);</pre>

<p>Wake up the device to fire a one-time (non-repeating) alarm in one minute:</p>

<pre>private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
        SystemClock.elapsedRealtime() +
        60 * 1000, alarmIntent);</pre>


<h4>RTC examples</h3>

<p>Here are some examples of using {@link android.app.AlarmManager#RTC_WAKEUP}.</p>

<p>Wake up the device to fire the alarm at approximately 2:00 p.m., and repeat once a day
at the same time:</p>

<pre>// Set the alarm to start at approximately 2:00 p.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 14);

// With setInexactRepeating(), you have to use one of the AlarmManager interval
// constants--in this case, AlarmManager.INTERVAL_DAY.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        AlarmManager.INTERVAL_DAY, alarmIntent);</pre>

<p>Wake up the device to fire the alarm at precisely 8:30 a.m., and every 20 minutes
thereafter:</p>

<pre>private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

// Set the alarm to start at 8:30 a.m.
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);

// setRepeating() lets you specify a precise custom interval--in this case,
// 20 minutes.
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
        1000 * 60 * 20, alarmIntent);</pre>

<h3>Decide how precise your alarm needs to be</h3>

<p>As described above, choosing the alarm type is often the first step in creating an alarm.
A further distinction is how precise you need your alarm to be. For most apps,
{@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()} is the right
choice.
When you use this method, Android synchronizes multiple inexact repeating alarms and fires
them at the same time. This reduces the drain on the battery.</p>

<p>For the rare app that has rigid time requirements&mdash;for example, the alarm needs to
fire precisely at 8:30 a.m., and every hour on the hour
thereafter&mdash;use {@link android.app.AlarmManager#setRepeating setRepeating()}. But you
should avoid using exact alarms if possible.</p>

<p>With {@link android.app.AlarmManager#setInexactRepeating setInexactRepeating()},
you can't specify a custom interval the way you can with
{@link android.app.AlarmManager#setRepeating setRepeating()}. You have to use one of the
interval constants, such as {@link android.app.AlarmManager#INTERVAL_FIFTEEN_MINUTES},
{@link android.app.AlarmManager#INTERVAL_DAY}, and so on. See {@link android.app.AlarmManager}
for the complete list.
</p>

<h2 id="cancel">Cancel an Alarm</h2>

<p>Depending on your app, you may want to include the ability to cancel the alarm.
To cancel an alarm, call {@link android.app.AlarmManager#cancel cancel()} on the Alarm
Manager, passing in the {@link android.app.PendingIntent} you no longer want to fire. For
example:</p>

<pre>// If the alarm has been set, cancel it.
if (alarmMgr!= null) {
    alarmMgr.cancel(alarmIntent);
}</pre>

<h2 id="boot">Start an Alarm When the Device Boots</h2>

<p>By default, all alarms are canceled when a device shuts down.
To prevent this from happening, you can design your application
to automatically restart a repeating alarm if the user reboots the device. This ensures
that the {@link android.app.AlarmManager} will continue doing its task without the user
needing to manually restart the alarm.</p>


<p>Here are the steps:</p>
<ol>
<li>Set the <a href="{@docRoot}reference/android/Manifest.permission.html#RECEIVE_BOOT_COMPLETED">
{@code RECEIVE_BOOT_COMPLETED}</a> permission in your application's manifest. This allows
your app to receive the
{@link android.content.Intent#ACTION_BOOT_COMPLETED} that is broadcast after the system
finishes booting (this only works if the app has already been launched by the user at least once):
<pre>
&lt;uses-permission android:name=&quot;android.permission.RECEIVE_BOOT_COMPLETED&quot;/&gt;</pre>
</li>

<li>Implement a {@link android.content.BroadcastReceiver} to receive the broadcast:
<pre>public class SampleBootReceiver extends BroadcastReceiver {

    &#64;Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(&quot;android.intent.action.BOOT_COMPLETED&quot;)) {
            // Set the alarm here.
        }
    }
}</pre></li>

<li>Add the receiver to your app's manifest file with an intent filter that filters on
the {@link android.content.Intent#ACTION_BOOT_COMPLETED} action:

<pre>&lt;receiver android:name=&quot;.SampleBootReceiver&quot;
        android:enabled=&quot;false&quot;&gt;
    &lt;intent-filter&gt;
        &lt;action android:name=&quot;android.intent.action.BOOT_COMPLETED&quot;&gt;&lt;/action&gt;
    &lt;/intent-filter&gt;
&lt;/receiver&gt;</pre>


<p>Notice that in the manifest, the boot receiver is set to
{@code android:enabled=&quot;false&quot;}. This means that the receiver will not be called
unless the application explicitly enables it. This prevents the boot receiver from being
called unnecessarily. You can enable a receiver (for example, if the user sets an alarm)
as follows:</p>

<pre>ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
PackageManager pm = context.getPackageManager();

pm.setComponentEnabledSetting(receiver,
        PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
        PackageManager.DONT_KILL_APP);
</pre>

<p>Once you enable the receiver this way, it will stay enabled, even if the user reboots
the device. In other words, programmatically enabling the receiver overrides the
manifest setting, even across reboots. The receiver will stay enabled until your app disables it.
You can disable a receiver (for example, if the user cancels an alarm) as follows:</p>

<pre>ComponentName receiver = new ComponentName(context, SampleBootReceiver.class);
PackageManager pm = context.getPackageManager();

pm.setComponentEnabledSetting(receiver,
        PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
        PackageManager.DONT_KILL_APP);</pre>

</li>
</ol>
+66 −0
Original line number Diff line number Diff line
page.title=Managing Device Awake State
page.tags=""

trainingnavtop=true
startpage=true


@jd:body
<div id="tb-wrapper">
<div id="tb">

<!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
<h2>Dependencies and prerequisites</h2>

<ul>
  <li>Android 1.6 (API Level 4) or higher</li>
</ul>

<h2>Try it out</h2>

<div class="download-box">
  <a href="{@docRoot}shareables/training/Scheduler.zip"
class="button">Download the sample</a>
 <p class="filename">Scheduler.zip</p>
</div>

</div>
</div>

<p>
When an Android device is left idle, it will first dim, then turn off the screen, and
ultimately turn off the CPU. This prevents the device's battery from quickly getting
drained. Yet there are times when your application might require a different behavior:</p>

<ul>

<li>Apps such as games or movie apps may need to keep the screen turned on.</p>

<li>Other applications may not need the screen to remain on, but they may require the CPU
 to keep running until a critical operation finishes.</p>

</ul>

<p>
This class describes how to keep a device awake when necessary without draining
its battery.
</p>
<h2>Lessons</h2>

<dl>
    <dt>
        <strong><a href="wakelock.html">Keeping the Device Awake</a></strong>
    </dt>
    <dd>
        Learn how to keep the screen or CPU awake as needed, while minimizing the impact
        on battery life.
    </dd>
    <dt>
        <strong><a href="alarms.html">Scheduling Repeating Alarms</a></strong>
    </dt>
    <dd>
        Learn how to use repeating alarms to schedule operations that take place outside
        of the lifetime of the application, even if the application is not running and/or the
        device is asleep.
    </dd>
</dl>
+215 −0
Original line number Diff line number Diff line
page.title=Keeping the Device Awake

trainingnavtop=true

@jd:body

<div id="tb-wrapper">
<div id="tb">

<!-- table of contents -->
<h2>This lesson teaches you to</h2>
<ol>
  <li><a href="#screen">Keep the Screen On</a></li>
  <li><a href="#cpu">Keep the CPU On</a></li>
</ol>

<h2>Try it out</h2>

<div class="download-box">
  <a href="{@docRoot}shareables/training/Scheduler.zip"
class="button">Download the sample</a>
 <p class="filename">Scheduler.zip</p>
</div>

</div>
</div>


<p>To avoid draining the battery, an Android device that is left idle quickly falls asleep.
However, there are times when an application needs to wake up the screen or the CPU
and keep it awake to complete some work.</p>

<p>The approach you take depends on the needs of your app. However, a general rule of thumb
is that you should use the most lightweight approach possible for your app, to minimize your
app's impact on system resources. The following sections describe how to handle the cases
where the device's default sleep behavior is incompatible with the requirements of your app.</p>

<h2 id="screen">Keep the Screen On</h2>

<p>Certain apps need to keep the screen turned on, such as games or movie apps. The best
way to do this is to use the
{@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON FLAG_KEEP_SCREEN_ON}
in your activity (and only in an activity, never in a service or
other app component). For example:</p>

<pre>public class MainActivity extends Activity {
  &#64;Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    <strong>getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);</strong>
  }</pre>

<p>The advantage of this approach is that unlike wake locks (discussed in <a href="#cpu">
Keep the CPU On</a>), it doesn't require special permission, and the platform correctly
manages the user moving between applications, without your app needing to worry about
releasing unused resources.</p>

<p>Another way to implement this is in your application's layout XML file, by using the
{@link android.R.attr#keepScreenOn android:keepScreenOn} attribute:</p>

<pre>&lt;RelativeLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    <strong>android:keepScreenOn=&quot;true&quot;&gt;</strong>
    ...
&lt;/RelativeLayout&gt;</pre>

<p>Using <code>android:keepScreenOn=&quot;true&quot;</code> is equivalent to using
{@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON FLAG_KEEP_SCREEN_ON}.
You can use whichever approach is best for your app. The advantage of setting the flag
programmatically in your activity is that it gives you the option of programmatically
clearing the flag later and thereby allowing the screen to turn off.</p>

<p class="note"><strong>Note:</strong> You don't need to clear the
{@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON FLAG_KEEP_SCREEN_ON}
flag unless you no longer want the screen to
stay on in your running application (for example, if you want the screen to time out
after a certain period of inactivity). The window manager takes care of
ensuring that the right things happen when the app goes into the background or returns to
the foreground. But if you want to explicitly clear the flag and thereby allow the screen to
turn off again, use {@link android.view.Window#clearFlags clearFlags()}:
{@code getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)}.</p>

<h2 id="cpu">Keep the CPU On</h2>

<div class="sidebox-wrapper">
<div class="sidebox">
  <h2>Alternatives to using wake locks</h2>

<ul>

<li>If your app is performing long-running HTTP downloads, consider using
{@link android.app.DownloadManager}.</li>

<li>If your app is synchronizing data from an external server, consider creating a
<a href="{@docRoot}training/sync-adapters/index.html">sync
adapter</a>.</li>

<li>If your app relies on background services, consider using
<a href="{@docRoot}training/scheduling/alarms.html">repeating alarms</a>
or <a href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a> to trigger these
services at specific intervals.</li>

</ul>
</div>
</div>


<p>If you need to keep the CPU running in order to complete some work before the device goes
to sleep, you can use a {@link android.os.PowerManager} system service feature called
wake locks. Wake locks allow your application to control the power state of the host device.</p>

<p>Creating and holding wake locks can have a dramatic impact on the host device's battery
life. Thus you should use wake locks only when strictly necessary
and hold them for as short a time as possible. For example, you should never need to use a
wake lock in an activity. As described above, if you want
to keep the screen on in your activity, use
{@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON FLAG_KEEP_SCREEN_ON}.</p>


<p>One legitimate case for using a wake lock might be a background service
that needs to grab a wake lock to keep the CPU running to do work while the screen is off.
Again, though, this practice should be minimized because of its impact on battery life.</p>

<p>To use a wake lock, the first step is to add the {@link android.Manifest.permission#WAKE_LOCK}
 permission to your application's manifest file:</p>

<pre>&lt;uses-permission android:name=&quot;android.permission.WAKE_LOCK&quot; /&gt;</pre>

<p>If your app includes a broadcast receiver that uses a service to do some
work, you can manage your wake lock through a
{@link android.support.v4.content.WakefulBroadcastReceiver}, as described in
<a href="#wakeful">Using a WakefulBroadcastReceiver</a>. This is the preferred approach.
If your app doesn't follow that pattern, here is how you set a wake lock
directly:</p>

<pre>
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
Wakelock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
        "MyWakelockTag");
wakeLock.acquire();</pre>

<p>To release the wake lock, call
{@link android.os.PowerManager.WakeLock#release wakelock.release()}. This releases your
claim to the CPU. It's important to release a wake lock as soon as your app is finished
using it to avoid draining the battery.</p>

<h3 id="wakeful">Using WakefulBroadcastReceiver</h3>

<p>Using a broadcast receiver in conjunction with a service lets you manage the life cycle
of a background task.</p>

<p>A {@link android.support.v4.content.WakefulBroadcastReceiver} is a special type of
broadcast receiver that takes care of
creating and managing a
{@link android.os.PowerManager#PARTIAL_WAKE_LOCK} for your app. A
{@link android.support.v4.content.WakefulBroadcastReceiver}
passes off the work to a {@link android.app.Service}
(typically an
{@link android.app.IntentService}), while ensuring that the device does not
go back to sleep in the transition. If you don't hold a wake lock while transitioning
the work to a service, you are effectively allowing the device to go back to sleep before
the work completes. The net result is that the app might not finish doing the work until
some arbitrary point in the future, which is not what you want.</p>

<p>The first step in using a
{@link android.support.v4.content.WakefulBroadcastReceiver} is to add it to your
manifest, as with any other broadcast receiver:</p>

<pre>&lt;receiver android:name=&quot;.MyWakefulReceiver&quot;&gt;&lt;/receiver&gt;</pre>

<p>The following code starts {@code MyIntentService} with the method
{@link android.support.v4.content.WakefulBroadcastReceiver#startWakefulService startWakefulService()}.
This method is comparable to {@link android.content.Context#startService startService()}, except that
the {@link android.support.v4.content.WakefulBroadcastReceiver} is holding a
wake lock when the service starts. The intent that is passed with
{@link android.support.v4.content.WakefulBroadcastReceiver#startWakefulService startWakefulService()}
holds an extra identifying the wake lock:</p>

<pre>public class MyWakefulReceiver extends WakefulBroadcastReceiver {

    &#64;Override
    public void onReceive(Context context, Intent intent) {

        // Start the service, keeping the device awake while the service is
        // launching. This is the Intent to deliver to the service.
        Intent service = new Intent(context, MyIntentService.class);
        startWakefulService(context, service);
    }
}</pre>

<p>When the service is finished, it calls
{@link android.support.v4.content.WakefulBroadcastReceiver#completeWakefulIntent MyWakefulReceiver.completeWakefulIntent()}
to release the wake lock. The
{@link android.support.v4.content.WakefulBroadcastReceiver#completeWakefulIntent completeWakefulIntent()}
method has as its parameter the same intent that was
passed in from the {@link android.support.v4.content.WakefulBroadcastReceiver}:</p>
<pre>
public class MyIntentService extends IntentService {
    public static final int NOTIFICATION_ID = 1;
    private NotificationManager mNotificationManager;
    NotificationCompat.Builder builder;
    public MyIntentService() {
        super("MyIntentService");
    }
    &#64;Override
    protected void onHandleIntent(Intent intent) {
        Bundle extras = intent.getExtras();
        // Do the work that requires your app to keep the CPU running.
        // ...
        // Release the wake lock provided by the WakefulBroadcastReceiver.
        MyWakefulReceiver.completeWakefulIntent(intent);
    }
}</pre>
Loading