1page.title=Keeping the Device Awake 2 3trainingnavtop=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" 21class="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. 30However, there are times when an application needs to wake up the screen or the CPU 31and 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 34is that you should use the most lightweight approach possible for your app, to minimize your 35app's impact on system resources. The following sections describe how to handle the cases 36where 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 41way to do this is to use the 42{@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON FLAG_KEEP_SCREEN_ON} 43in your activity (and only in an activity, never in a service or 44other app component). For example:</p> 45 46<pre>public class MainActivity extends Activity { 47 @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"> 55Keep the CPU On</a>), it doesn't require special permission, and the platform correctly 56manages the user moving between applications, without your app needing to worry about 57releasing 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><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 63 android:layout_width="match_parent" 64 android:layout_height="match_parent" 65 <strong>android:keepScreenOn="true"></strong> 66 ... 67</RelativeLayout></pre> 68 69<p>Using <code>android:keepScreenOn="true"</code> is equivalent to using 70{@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON FLAG_KEEP_SCREEN_ON}. 71You can use whichever approach is best for your app. The advantage of setting the flag 72programmatically in your activity is that it gives you the option of programmatically 73clearing 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} 77flag unless you no longer want the screen to 78stay on in your running application (for example, if you want the screen to time out 79after a certain period of inactivity). The window manager takes care of 80ensuring that the right things happen when the app goes into the background or returns to 81the foreground. But if you want to explicitly clear the flag and thereby allow the screen to 82turn 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 98adapter</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> 102or <a href="{@docRoot}google/gcm/index.html">Google Cloud Messaging</a> to trigger these 103services 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 111to sleep, you can use a {@link android.os.PowerManager} system service feature called 112wake 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 115life. Thus you should use wake locks only when strictly necessary 116and hold them for as short a time as possible. For example, you should never need to use a 117wake lock in an activity. As described above, if you want 118to 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 123that needs to grab a wake lock to keep the CPU running to do work while the screen is off. 124Again, 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><uses-permission android:name="android.permission.WAKE_LOCK" /></pre> 130 131<p>If your app includes a broadcast receiver that uses a service to do some 132work, 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. 135If your app doesn't follow that pattern, here is how you set a wake lock 136directly:</p> 137 138<pre> 139PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); 140Wakelock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 141 "MyWakelockTag"); 142wakeLock.acquire();</pre> 143 144<p>To release the wake lock, call 145{@link android.os.PowerManager.WakeLock#release wakelock.release()}. This releases your 146claim to the CPU. It's important to release a wake lock as soon as your app is finished 147using 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 152of a background task.</p> 153 154<p>A {@link android.support.v4.content.WakefulBroadcastReceiver} is a special type of 155broadcast receiver that takes care of 156creating and managing a 157{@link android.os.PowerManager#PARTIAL_WAKE_LOCK} for your app. A 158{@link android.support.v4.content.WakefulBroadcastReceiver} 159passes off the work to a {@link android.app.Service} 160(typically an 161{@link android.app.IntentService}), while ensuring that the device does not 162go back to sleep in the transition. If you don't hold a wake lock while transitioning 163the work to a service, you are effectively allowing the device to go back to sleep before 164the work completes. The net result is that the app might not finish doing the work until 165some 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 169manifest, as with any other broadcast receiver:</p> 170 171<pre><receiver android:name=".MyWakefulReceiver"></receiver></pre> 172 173<p>The following code starts {@code MyIntentService} with the method 174{@link android.support.v4.content.WakefulBroadcastReceiver#startWakefulService startWakefulService()}. 175This method is comparable to {@link android.content.Context#startService startService()}, except that 176the {@link android.support.v4.content.WakefulBroadcastReceiver} is holding a 177wake lock when the service starts. The intent that is passed with 178{@link android.support.v4.content.WakefulBroadcastReceiver#startWakefulService startWakefulService()} 179holds an extra identifying the wake lock:</p> 180 181<pre>public class MyWakefulReceiver extends WakefulBroadcastReceiver { 182 183 @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()} 195to release the wake lock. The 196{@link android.support.v4.content.WakefulBroadcastReceiver#completeWakefulIntent completeWakefulIntent()} 197method has as its parameter the same intent that was 198passed in from the {@link android.support.v4.content.WakefulBroadcastReceiver}:</p> 199<pre> 200public 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 @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