Home | History | Annotate | Download | only in scheduling
      1 page.title=Keeping the Device Awake
      2 
      3 trainingnavtop=true
      4 
      5 @jd:body
      6 
      7 <div id="tb-wrapper">
      8 <div id="tb">
      9 
     10 <!-- table of contents -->
     11 <h2>This lesson teaches you to</h2>
     12 <ol>
     13   <li><a href="#screen">Keep the Screen On</a></li>
     14   <li><a href="#cpu">Keep the CPU On</a></li>
     15 </ol>
     16 
     17 <h2>Try it out</h2>
     18 
     19 <div class="download-box">
     20   <a href="{@docRoot}shareables/training/Scheduler.zip"
     21 class="button">Download the sample</a>
     22  <p class="filename">Scheduler.zip</p>
     23 </div>
     24 
     25 </div>
     26 </div>
     27 
     28 
     29 <p>To avoid draining the battery, an Android device that is left idle quickly falls asleep.
     30 However, there are times when an application needs to wake up the screen or the CPU
     31 and keep it awake to complete some work.</p>
     32 
     33 <p>The approach you take depends on the needs of your app. However, a general rule of thumb
     34 is that you should use the most lightweight approach possible for your app, to minimize your
     35 app's impact on system resources. The following sections describe how to handle the cases
     36 where the device's default sleep behavior is incompatible with the requirements of your app.</p>
     37 
     38 <h2 id="screen">Keep the Screen On</h2>
     39 
     40 <p>Certain apps need to keep the screen turned on, such as games or movie apps. The best
     41 way to do this is to use the
     42 {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON FLAG_KEEP_SCREEN_ON}
     43 in your activity (and only in an activity, never in a service or
     44 other app component). For example:</p>
     45 
     46 <pre>public class MainActivity extends Activity {
     47   &#64;Override
     48   protected void onCreate(Bundle savedInstanceState) {
     49     super.onCreate(savedInstanceState);
     50     setContentView(R.layout.activity_main);
     51     <strong>getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);</strong>
     52   }</pre>
     53 
     54 <p>The advantage of this approach is that unlike wake locks (discussed in <a href="#cpu">
     55 Keep the CPU On</a>), it doesn't require special permission, and the platform correctly
     56 manages the user moving between applications, without your app needing to worry about
     57 releasing unused resources.</p>
     58 
     59 <p>Another way to implement this is in your application's layout XML file, by using the
     60 {@link android.R.attr#keepScreenOn android:keepScreenOn} attribute:</p>
     61 
     62 <pre>&lt;RelativeLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android";
     63     android:layout_width=&quot;match_parent&quot;
     64     android:layout_height=&quot;match_parent&quot;
     65     <strong>android:keepScreenOn=&quot;true&quot;&gt;</strong>
     66     ...
     67 &lt;/RelativeLayout&gt;</pre>
     68 
     69 <p>Using <code>android:keepScreenOn=&quot;true&quot;</code> is equivalent to using
     70 {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON FLAG_KEEP_SCREEN_ON}.
     71 You can use whichever approach is best for your app. The advantage of setting the flag
     72 programmatically in your activity is that it gives you the option of programmatically
     73 clearing the flag later and thereby allowing the screen to turn off.</p>
     74 
     75 <p class="note"><strong>Note:</strong> You don't need to clear the
     76 {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON FLAG_KEEP_SCREEN_ON}
     77 flag unless you no longer want the screen to
     78 stay on in your running application (for example, if you want the screen to time out
     79 after a certain period of inactivity). The window manager takes care of
     80 ensuring that the right things happen when the app goes into the background or returns to
     81 the foreground. But if you want to explicitly clear the flag and thereby allow the screen to
     82 turn off again, use {@link android.view.Window#clearFlags clearFlags()}:
     83 {@code getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)}.</p>
     84 
     85 <h2 id="cpu">Keep the CPU On</h2>
     86 
     87 <div class="sidebox-wrapper">
     88 <div class="sidebox">
     89   <h2>Alternatives to using wake locks</h2>
     90 
     91 <ul>
     92 
     93 <li>If your app is performing long-running HTTP downloads, consider using
     94 {@link android.app.DownloadManager}.</li>
     95 
     96 <li>If your app is synchronizing data from an external server, consider creating a
     97 <a href="{@docRoot}training/sync-adapters/index.html">sync
     98 adapter</a>.</li>
     99 
    100 <li>If your app relies on background services, consider using
    101 <a href="{@docRoot}training/scheduling/alarms.html">repeating alarms</a>
    102 or <a href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a> to trigger these
    103 services at specific intervals.</li>
    104 
    105 </ul>
    106 </div>
    107 </div>
    108 
    109 
    110 <p>If you need to keep the CPU running in order to complete some work before the device goes
    111 to sleep, you can use a {@link android.os.PowerManager} system service feature called
    112 wake locks. Wake locks allow your application to control the power state of the host device.</p>
    113 
    114 <p>Creating and holding wake locks can have a dramatic impact on the host device's battery
    115 life. Thus you should use wake locks only when strictly necessary
    116 and hold them for as short a time as possible. For example, you should never need to use a
    117 wake lock in an activity. As described above, if you want
    118 to keep the screen on in your activity, use
    119 {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON FLAG_KEEP_SCREEN_ON}.</p>
    120 
    121 
    122 <p>One legitimate case for using a wake lock might be a background service
    123 that needs to grab a wake lock to keep the CPU running to do work while the screen is off.
    124 Again, though, this practice should be minimized because of its impact on battery life.</p>
    125 
    126 <p>To use a wake lock, the first step is to add the {@link android.Manifest.permission#WAKE_LOCK}
    127  permission to your application's manifest file:</p>
    128 
    129 <pre>&lt;uses-permission android:name=&quot;android.permission.WAKE_LOCK&quot; /&gt;</pre>
    130 
    131 <p>If your app includes a broadcast receiver that uses a service to do some
    132 work, you can manage your wake lock through a
    133 {@link android.support.v4.content.WakefulBroadcastReceiver}, as described in
    134 <a href="#wakeful">Using a WakefulBroadcastReceiver</a>. This is the preferred approach.
    135 If your app doesn't follow that pattern, here is how you set a wake lock
    136 directly:</p>
    137 
    138 <pre>
    139 PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
    140 Wakelock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
    141         "MyWakelockTag");
    142 wakeLock.acquire();</pre>
    143 
    144 <p>To release the wake lock, call
    145 {@link android.os.PowerManager.WakeLock#release wakelock.release()}. This releases your
    146 claim to the CPU. It's important to release a wake lock as soon as your app is finished
    147 using it to avoid draining the battery.</p>
    148 
    149 <h3 id="wakeful">Using WakefulBroadcastReceiver</h3>
    150 
    151 <p>Using a broadcast receiver in conjunction with a service lets you manage the life cycle
    152 of a background task.</p>
    153 
    154 <p>A {@link android.support.v4.content.WakefulBroadcastReceiver} is a special type of
    155 broadcast receiver that takes care of
    156 creating and managing a
    157 {@link android.os.PowerManager#PARTIAL_WAKE_LOCK} for your app. A
    158 {@link android.support.v4.content.WakefulBroadcastReceiver}
    159 passes off the work to a {@link android.app.Service}
    160 (typically an
    161 {@link android.app.IntentService}), while ensuring that the device does not
    162 go back to sleep in the transition. If you don't hold a wake lock while transitioning
    163 the work to a service, you are effectively allowing the device to go back to sleep before
    164 the work completes. The net result is that the app might not finish doing the work until
    165 some arbitrary point in the future, which is not what you want.</p>
    166 
    167 <p>The first step in using a
    168 {@link android.support.v4.content.WakefulBroadcastReceiver} is to add it to your
    169 manifest, as with any other broadcast receiver:</p>
    170 
    171 <pre>&lt;receiver android:name=&quot;.MyWakefulReceiver&quot;&gt;&lt;/receiver&gt;</pre>
    172 
    173 <p>The following code starts {@code MyIntentService} with the method
    174 {@link android.support.v4.content.WakefulBroadcastReceiver#startWakefulService startWakefulService()}.
    175 This method is comparable to {@link android.content.Context#startService startService()}, except that
    176 the {@link android.support.v4.content.WakefulBroadcastReceiver} is holding a
    177 wake lock when the service starts. The intent that is passed with
    178 {@link android.support.v4.content.WakefulBroadcastReceiver#startWakefulService startWakefulService()}
    179 holds an extra identifying the wake lock:</p>
    180 
    181 <pre>public class MyWakefulReceiver extends WakefulBroadcastReceiver {
    182 
    183     &#64;Override
    184     public void onReceive(Context context, Intent intent) {
    185 
    186         // Start the service, keeping the device awake while the service is
    187         // launching. This is the Intent to deliver to the service.
    188         Intent service = new Intent(context, MyIntentService.class);
    189         startWakefulService(context, service);
    190     }
    191 }</pre>
    192 
    193 <p>When the service is finished, it calls
    194 {@link android.support.v4.content.WakefulBroadcastReceiver#completeWakefulIntent MyWakefulReceiver.completeWakefulIntent()}
    195 to release the wake lock. The
    196 {@link android.support.v4.content.WakefulBroadcastReceiver#completeWakefulIntent completeWakefulIntent()}
    197 method has as its parameter the same intent that was
    198 passed in from the {@link android.support.v4.content.WakefulBroadcastReceiver}:</p>
    199 <pre>
    200 public class MyIntentService extends IntentService {
    201     public static final int NOTIFICATION_ID = 1;
    202     private NotificationManager mNotificationManager;
    203     NotificationCompat.Builder builder;
    204     public MyIntentService() {
    205         super("MyIntentService");
    206     }
    207     &#64;Override
    208     protected void onHandleIntent(Intent intent) {
    209         Bundle extras = intent.getExtras();
    210         // Do the work that requires your app to keep the CPU running.
    211         // ...
    212         // Release the wake lock provided by the WakefulBroadcastReceiver.
    213         MyWakefulReceiver.completeWakefulIntent(intent);
    214     }
    215 }</pre>
    216