page.title=Optimizing Performance and Battery Life @jd:body <div id="tb-wrapper"> <div id="tb"> <h2>This lesson teaches you to</h2> <ol> <li><a href="#Basic">Basic Optimization</a></li> <li><a href="#Animations">Best Practices for Animations</a></li> <li><a href="#ReduceSize">Reduce the Size of Your Bitmap Assets</a></li> <li><a href="#CombineBitmaps">Combine Bitmap Assets</a></li> <li><a href="#AntiAlias">Disable Anti-Aliasing when Drawing Scaled Bitmaps</a></li> <li><a href="#OutDrawing">Move Expensive Operations Outside the Drawing Method</a></li> </ol> <h2>You should also read</h2> <ul> <li><a href="{@docRoot}design/wear/watchfaces.html">Watch Faces for Android Wear</a></li> <li><a href="http://android-developers.blogspot.com/2014/12/making-performant-watch-face.html"> Making a performant watch face</a></li> <li><a href="http://android-developers.blogspot.com/2016/04/deprecation-of-bindlistener.html"> Deprecation of BIND_LISTENER with Android Wear APIs</a></li> </ul> </div> </div> <p>This lesson has tips for conserving power and improving performance. A watch face runs continuously, so it must use power efficiently. </p> <p>Services must not perform unnecessary computations. Watch faces with animations must run smoothly while accommodating notification cards and system indicators.</p> <h2 id="Basic">Basic Optimization</h2> <p>This section contains best practices for improving efficiency during periods when a watch face is inactive.</p> <h3>Use callbacks in WatchFaceService.Engine</h3> <p>Ensure that your watch face performs computations only when active; use callbacks in <a href="{@docRoot}reference/android/support/wearable/watchface/ WatchFaceService.Engine.html">{@code WatchFaceService.Engine}</a>. Preferably, use the following methods of that class to determine if the watch face is visible:</p> <ul> <li>{@code onVisibilityChanged(boolean)}</li> <li>{@code isVisible()}</li> </ul> <p>Alternatively, use the following methods of the same class (<a href="{@docRoot}reference/android/support/wearable/watchface/ WatchFaceService.Engine.html">{@code WatchFaceService.Engine}</a>):</p> <ul> <li>{@code onCreate()}</li> <li>{@code onDestroy()}</li> </ul> <h3>Use listeners registered with the DataApi interface</h3> <p>To listen for events, use live listeners that are registered with <a href="https://developers.google.com/android/reference/com/google/ android/gms/wearable/DataApi.html#addListener (com.google.android.gms.common.api.GoogleApiClient, com. google.android.gms.wearable.DataApi.DataListener)">{@code DataApi.addListener}</a>. For an example, see <a href="{@docRoot}training/wearables/data-layer/ data-items.html#ListenEvents">Syncing Data Items</a>.</p> <p>Do not use <a href="https://developers.google.com/ android/reference/com/google/android/gms/wearable/ WearableListenerService">{@code WearableListenerService}</a> to listen for events, because it is called whether or not a watch face is active. For more information, see <a href="http://android-developers.blogspot.com/2016/04/ deprecation-of-bindlistener.html">Deprecation of BIND_LISTENER with Android Wear APIs</a>.</p> <p>Do not register a broadcast receiver in the Android manifest file to get system events such as time zone changes, battery events, etc., because the <a href="{@docRoot}reference/android/content/BroadcastReceiver.html">{@code BroadcastReceiver}</a> is called whether or not a watch face is active. However, you can use the <a href="{@docRoot}reference/android/content/Context.html#registerReceiver(android. content.BroadcastReceiver, android.content.IntentFilter)">{@code registerReceiver}</a> method of the {@code Context} class to register a receiver.</p> <h3>Monitor power consumption</h3> <p>The <a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en"> Android Wear companion app</a> enables developers and users to see how much battery is consumed by different processes on the wearable device (under <strong>Settings</strong> > <strong>Watch battery</strong>).</p> <p>For information about features introduced in Android 5.0 that help you improve battery life, see <a href="{@docRoot}about/versions/android-5.0.html#Power">Project Volta</a>.</p> <h2 id="Animations">Best Practices for Animations</h2> <p>The best practices in this section help to reduce the power consumption of animations.</p> <h3>Reduce the frame rate of animations</h3> <p>Animations are often computationally expensive and consume a significant amount of power. Most animations look fluid at 30 frames per second, so you should avoid running your animations at a higher frame rate.</p> <h3>Let the CPU sleep between animations</h3> <p>Animations and small changes to the contents of the watch face wake up the CPU. Your watch face should let the CPU sleep in between animations. For example, you can use short bursts of animation every second in interactive mode and then let the CPU sleep until the next second. Letting the CPU sleep often, even briefly, can significantly reduce power consumption.</p> <p>To maximize battery life, use animations sparingly. Even a blinking colon wakes up the CPU with every blink and hurts battery life.</p> <h2 id="ReduceSize">Reduce the Size of Your Bitmap Assets</h2> <p>Many watch faces consist of a background image and other graphic assets that are transformed and overlapped on top of the background image, such as clock hands and other elements of the design that move over time. Typically these graphic elements are rotated (and sometimes scaled) inside the <a href="{@docRoot}reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html#onDraw(android.graphics.Canvas, android.graphics.Rect)"><code>Engine.onDraw()</code></a> method every time the system redraws the watch face, as described in <a href="{@docRoot}training/wearables/watch-faces/drawing.html#Drawing">Draw Your Watch Face</a>.</p> <p>The larger these graphic assets are, the more computationally expensive it is to transform them. Transforming large graphic assets in the <a href="{@docRoot}reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html#onDraw(android.graphics.Canvas, android.graphics.Rect)"><code>Engine.onDraw()</code></a> method drastically reduces the frame rate at which the system can run your animations.</p> <div id="fig1" style="float:right;width:250px;margin-left:25px"> <img src="{@docRoot}training/wearables/watch-faces/images/ClockHandFull.png" alt="" width="180" height="180"/> <img src="{@docRoot}training/wearables/watch-faces/images/ClockHandCropped.png" alt="" width="15" height="65" style="margin-left:25px"/> <p class="img-caption"> <strong>Figure 1.</strong> Clock hands can be cropped to remove extra pixels.</p> </div> <p>To improve the performance of your watch face:</p> <ul> <li>Do not use graphic elements that are larger than you need.</li> <li>Remove extra transparent pixels around the edges.</li> </ul> <p>The example clock hand on the left side of <a href="#fig1">Figure 1</a> can be reduced in size by 97%.</p> <p>Reducing the size of your bitmap assets as described in this section not only improves the performance of your animations, but it also saves power.</p> <h2 id="CombineBitmaps">Combine Bitmap Assets</h2> <p>If you have bitmaps that are often drawn together, consider combining them into the same graphic asset. You can often combine the background image in interactive mode with the tick marks to avoid drawing two full-screen bitmaps every time the system redraws the watch face.</p> <h2 id="AntiAlias">Disable Anti-Aliasing when Drawing Scaled Bitmaps</h2> <p>When you draw a scaled bitmap on the {@link android.graphics.Canvas} object using the {@link android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint) Canvas.drawBitmap()} method, you can provide a {@link android.graphics.Paint} instance to configure several options. To improve performance, disable anti-aliasing using the {@link android.graphics.Paint#setAntiAlias setAntiAlias()} method, since this option does not have any effect on bitmaps.</p> <div id="fig2" style="float:right;width:250px;margin-left:40px;margin-top:12px"> <img src="{@docRoot}training/wearables/watch-faces/images/BitmapFilterDisabled.png" alt="" width="70" height="70" style="margin-left:20px"/> <img src="{@docRoot}training/wearables/watch-faces/images/BitmapFilterEnabled.png" alt="" width="70" height="70" style="margin-left:20px"/> <p class="img-caption"><strong>Figure 2.</strong> Example of bitmap filtering disabled (left) and enabled (right).</p> </div> <h3 id="BitmapFiltering">Use bitmap filtering</h3> <p>For bitmap assets that you draw on top of other elements, enable bitmap filtering on the same {@link android.graphics.Paint} instance using the {@link android.graphics.Paint#setFilterBitmap setFilterBitmap()} method. <a href="#fig2">Figure 2</a> shows a magnified view of a clock hand with and without bitmap filtering.</p> <p class="note"><strong>Note:</strong> In low-bit ambient mode, the system does not reliably render the colors in the image for bitmap filtering to process successfully. When ambient mode is active, disable bitmap filtering.</p> <h2 id="OutDrawing">Move Expensive Operations Outside the Drawing Method</h2> <p>The system calls the <a href="{@docRoot}reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html#onDraw(android.graphics.Canvas, android.graphics.Rect)"><code>Engine.onDraw()</code></a> method every time it redraws your watch face, so you should only include operations that are strictly required to update the watch face inside this method to improve performance.<p> <p>When possible, avoid performing these operations inside the <a href="{@docRoot}reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html#onDraw(android.graphics.Canvas, android.graphics.Rect)"><code>Engine.onDraw()</code></a> method:</p> <ul> <li>Loading images and other resources.</li> <li>Resizing images.</li> <li>Allocating objects.</li> <li>Performing computations whose result does not change between frames.</li> </ul> <p>You can usually perform these operations in the <a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onCreate(android.view.SurfaceHolder)"><code>Engine.onCreate()</code></a> method instead. You can resize images ahead of time in the {@link android.service.wallpaper.WallpaperService.Engine#onSurfaceChanged(android.view.SurfaceHolder, int, int, int) Engine.onSurfaceChanged()} method, which provides you with the size of the canvas.</p> <p>To analyze the performance of your watch face, use the Android Device Monitor. In particular, ensure that the execution time for your <a href="{@docRoot}reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html#onDraw(android.graphics.Canvas, android.graphics.Rect)"><code>Engine.onDraw()</code></a> implementation is short and consistent across invocations. For more information, see <a href="{@docRoot}tools/debugging/ddms.html">Using DDMS</a>.</p>