diff options
Diffstat (limited to 'docs/html/training/scheduling/wakelock.jd')
-rw-r--r-- | docs/html/training/scheduling/wakelock.jd | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/docs/html/training/scheduling/wakelock.jd b/docs/html/training/scheduling/wakelock.jd new file mode 100644 index 0000000..0fab7be --- /dev/null +++ b/docs/html/training/scheduling/wakelock.jd @@ -0,0 +1,215 @@ +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> |