| 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 { |
| @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><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| android:layout_width="match_parent" |
| android:layout_height="match_parent" |
| <strong>android:keepScreenOn="true"></strong> |
| ... |
| </RelativeLayout></pre> |
| |
| <p>Using <code>android:keepScreenOn="true"</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><uses-permission android:name="android.permission.WAKE_LOCK" /></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><receiver android:name=".MyWakefulReceiver"></receiver></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 { |
| |
| @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"); |
| } |
| @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> |