Home | History | Annotate | Download | only in watch-faces
      1 page.title=Optimizing Performance and Battery Life
      2 
      3 @jd:body
      4 
      5 <div id="tb-wrapper">
      6 <div id="tb">
      7 <h2>This lesson teaches you to</h2>
      8 <ol>
      9   <li><a href="#Basic">Basic Optimization</a></li>
     10   <li><a href="#Animations">Best Practices for Animations</a></li>
     11   <li><a href="#ReduceSize">Reduce the Size of Your Bitmap Assets</a></li>
     12   <li><a href="#CombineBitmaps">Combine Bitmap Assets</a></li>
     13   <li><a href="#AntiAlias">Disable Anti-Aliasing when Drawing Scaled Bitmaps</a></li>
     14   <li><a href="#OutDrawing">Move Expensive Operations Outside the Drawing Method</a></li>
     15 </ol>
     16 <h2>You should also read</h2>
     17 <ul>
     18   <li><a href="{@docRoot}design/wear/watchfaces.html">Watch Faces for Android Wear</a></li>
     19   <li><a href="http://android-developers.blogspot.com/2014/12/making-performant-watch-face.html">
     20 Making a performant watch face</a></li>
     21   <li><a href="http://android-developers.blogspot.com/2016/04/deprecation-of-bindlistener.html">
     22 Deprecation of BIND_LISTENER with Android Wear APIs</a></li>
     23 </ul>
     24 </div>
     25 </div>
     26 
     27 <p>This lesson has tips for conserving power and improving performance.
     28 A watch face runs continuously, so it must use power
     29 efficiently. </p>
     30 
     31 <p>Services must not perform unnecessary computations.
     32 Watch faces with animations must run smoothly while accommodating
     33 notification cards and system indicators.</p>
     34 
     35 <h2 id="Basic">Basic Optimization</h2>
     36 
     37 <p>This section contains best practices for improving efficiency during
     38 periods when a watch face is inactive.</p>
     39 
     40 <h3>Use callbacks in WatchFaceService.Engine</h3>
     41 
     42 <p>Ensure that your watch face performs
     43 computations only when active; use callbacks
     44 in <a href="{@docRoot}reference/android/support/wearable/watchface/
     45 WatchFaceService.Engine.html">{@code WatchFaceService.Engine}</a>.
     46 Preferably, use the following methods of that class to determine if
     47 the watch face is visible:</p>
     48 
     49 <ul>
     50   <li>{@code onVisibilityChanged(boolean)}</li>
     51   <li>{@code isVisible()}</li>
     52 </ul>
     53 
     54 <p>Alternatively, use the following methods of the same class
     55 (<a href="{@docRoot}reference/android/support/wearable/watchface/
     56 WatchFaceService.Engine.html">{@code WatchFaceService.Engine}</a>):</p>
     57 
     58 <ul>
     59   <li>{@code onCreate()}</li>
     60   <li>{@code onDestroy()}</li>
     61 </ul>
     62 
     63 <h3>Use listeners registered with the DataApi interface</h3>
     64 
     65 <p>To listen for events, use live listeners that are registered
     66 with <a href="https://developers.google.com/android/reference/com/google/
     67 android/gms/wearable/DataApi.html#addListener
     68 (com.google.android.gms.common.api.GoogleApiClient, com.
     69 google.android.gms.wearable.DataApi.DataListener)">{@code DataApi.addListener}</a>.
     70 For an example, see <a href="{@docRoot}training/wearables/data-layer/
     71 data-items.html#ListenEvents">Syncing Data Items</a>.</p>
     72 
     73 <p>Do not use <a href="https://developers.google.com/
     74 android/reference/com/google/android/gms/wearable/
     75 WearableListenerService">{@code WearableListenerService}</a> to listen for
     76 events, because it is
     77 called whether or not a watch face is active. For more information, see
     78 <a href="http://android-developers.blogspot.com/2016/04/
     79 deprecation-of-bindlistener.html">Deprecation of BIND_LISTENER
     80 with Android Wear APIs</a>.</p>
     81 
     82 <p>Do not register a broadcast receiver in the Android manifest file
     83 to get system events such as time zone changes, battery events, etc., because
     84 the <a href="{@docRoot}reference/android/content/BroadcastReceiver.html">{@code BroadcastReceiver}</a>
     85 is called whether or not a watch face is active. However, you can use the
     86 <a href="{@docRoot}reference/android/content/Context.html#registerReceiver(android.
     87 content.BroadcastReceiver, android.content.IntentFilter)">{@code registerReceiver}</a> method
     88 of the {@code Context} class to register a receiver.</p>
     89 
     90 <h3>Monitor power consumption</h3>
     91 
     92 <p>The <a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en">
     93 Android Wear companion app</a> enables developers and users to see how much battery
     94 is consumed by different processes
     95 on the wearable device (under <strong>Settings</strong> > <strong>Watch
     96 battery</strong>).</p>
     97 
     98 <p>For information about features introduced in Android 5.0 that help you improve battery life,
     99 see <a href="{@docRoot}about/versions/android-5.0.html#Power">Project Volta</a>.</p>
    100 
    101 <h2 id="Animations">Best Practices for Animations</h2>
    102 
    103 <p>The best practices in this section help to reduce the power consumption of animations.</p>
    104 
    105 <h3>Reduce the frame rate of animations</h3>
    106 
    107 <p>Animations are often computationally expensive and consume a significant amount of power. Most
    108 animations look fluid at 30 frames per second, so you should avoid running your animations
    109 at a higher frame rate.</p>
    110 
    111 <h3>Let the CPU sleep between animations</h3>
    112 
    113 <p>Animations and small changes to the contents of the watch face wake up the CPU. Your watch
    114 face should let the CPU sleep in between animations. For example, you can use short bursts of
    115 animation every second in interactive mode and then let the CPU sleep until the next second.
    116 Letting the CPU sleep often, even briefly, can significantly reduce power consumption.</p>
    117 
    118 <p>To maximize battery life, use animations sparingly. Even a blinking colon wakes up the CPU with
    119 every blink and hurts battery life.</p>
    120 
    121 <h2 id="ReduceSize">Reduce the Size of Your Bitmap Assets</h2>
    122 
    123 <p>Many watch faces consist of a background image and other graphic assets that are transformed
    124 and overlapped on top of the background image, such as clock hands and other elements of the design
    125 that move over time. Typically these graphic elements are rotated (and sometimes scaled) inside the
    126 <a href="{@docRoot}reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html#onDraw(android.graphics.Canvas, android.graphics.Rect)"><code>Engine.onDraw()</code></a>
    127 method every time the system redraws the watch face, as described in
    128 <a href="{@docRoot}training/wearables/watch-faces/drawing.html#Drawing">Draw Your Watch
    129 Face</a>.</p>
    130 
    131 <p>The larger these graphic assets are, the more computationally expensive it is to transform them.
    132 Transforming large graphic assets in the
    133 <a href="{@docRoot}reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html#onDraw(android.graphics.Canvas, android.graphics.Rect)"><code>Engine.onDraw()</code></a>
    134 method drastically reduces the frame rate at which the system can run your animations.</p>
    135 
    136 <div id="fig1" style="float:right;width:250px;margin-left:25px">
    137 <img src="{@docRoot}training/wearables/watch-faces/images/ClockHandFull.png" alt=""
    138      width="180" height="180"/>
    139 <img src="{@docRoot}training/wearables/watch-faces/images/ClockHandCropped.png" alt=""
    140      width="15" height="65" style="margin-left:25px"/>
    141 <p class="img-caption">
    142 <strong>Figure 1.</strong> Clock hands can be cropped to remove extra pixels.</p>
    143 </div>
    144 
    145 <p>To improve the performance of your watch face:</p>
    146 
    147 <ul>
    148 <li>Do not use graphic elements that are larger than you need.</li>
    149 <li>Remove extra transparent pixels around the edges.</li>
    150 </ul>
    151 
    152 <p>The example clock hand on the left side of <a href="#fig1">Figure 1</a> can be reduced in size
    153 by 97&#37;.</p>
    154 
    155 <p>Reducing the size of your bitmap assets as described in this section not only improves
    156 the performance of your animations, but it also saves power.</p>
    157 
    158 <h2 id="CombineBitmaps">Combine Bitmap Assets</h2>
    159 
    160 <p>If you have bitmaps that are often drawn together, consider combining them into the same
    161 graphic asset. You can often combine the background image in interactive mode with the tick
    162 marks to avoid drawing two full-screen bitmaps every time the system redraws the watch face.</p>
    163 
    164 <h2 id="AntiAlias">Disable Anti-Aliasing when Drawing Scaled Bitmaps</h2>
    165 
    166 <p>When you draw a scaled bitmap on the {@link android.graphics.Canvas} object using the {@link
    167 android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint)
    168 Canvas.drawBitmap()} method, you can provide a {@link android.graphics.Paint} instance to configure
    169 several options. To improve performance, disable anti-aliasing using the {@link
    170 android.graphics.Paint#setAntiAlias setAntiAlias()} method, since this option does not have any
    171 effect on bitmaps.</p>
    172 
    173 <div id="fig2" style="float:right;width:250px;margin-left:40px;margin-top:12px">
    174 <img src="{@docRoot}training/wearables/watch-faces/images/BitmapFilterDisabled.png" alt=""
    175      width="70" height="70" style="margin-left:20px"/>
    176 <img src="{@docRoot}training/wearables/watch-faces/images/BitmapFilterEnabled.png" alt=""
    177      width="70" height="70" style="margin-left:20px"/>
    178 <p class="img-caption"><strong>Figure 2.</strong> Example of bitmap filtering disabled (left) and
    179 enabled (right).</p>
    180 </div>
    181 
    182 <h3 id="BitmapFiltering">Use bitmap filtering</h3>
    183 
    184 <p>For bitmap assets that you draw on top of other elements, enable bitmap filtering on the same
    185 {@link android.graphics.Paint} instance using the {@link android.graphics.Paint#setFilterBitmap
    186 setFilterBitmap()} method. <a href="#fig2">Figure 2</a> shows a magnified view of a clock hand with
    187 and without bitmap filtering.</p>
    188 
    189 <p class="note"><strong>Note:</strong> In low-bit ambient mode, the system does not reliably
    190 render the colors in the image for bitmap filtering to process successfully. When ambient mode is
    191 active, disable bitmap filtering.</p>
    192 
    193 <h2 id="OutDrawing">Move Expensive Operations Outside the Drawing Method</h2>
    194 
    195 <p>The system calls the
    196 <a href="{@docRoot}reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html#onDraw(android.graphics.Canvas, android.graphics.Rect)"><code>Engine.onDraw()</code></a>
    197 method every time it redraws your watch face, so you should only include operations that are
    198 strictly required to update the watch face inside this method to improve performance.<p>
    199 
    200 <p>When possible, avoid performing these operations inside the
    201 <a href="{@docRoot}reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html#onDraw(android.graphics.Canvas, android.graphics.Rect)"><code>Engine.onDraw()</code></a>
    202 method:</p>
    203 
    204 <ul>
    205 <li>Loading images and other resources.</li>
    206 <li>Resizing images.</li>
    207 <li>Allocating objects.</li>
    208 <li>Performing computations whose result does not change between frames.</li>
    209 </ul>
    210 
    211 <p>You can usually perform these operations in the
    212 <a href="{@docRoot}reference/android/support/wearable/watchface/WatchFaceService.Engine.html#onCreate(android.view.SurfaceHolder)"><code>Engine.onCreate()</code></a>
    213 method instead.
    214 You can resize images ahead of time in the {@link
    215 android.service.wallpaper.WallpaperService.Engine#onSurfaceChanged(android.view.SurfaceHolder, int, int, int)
    216 Engine.onSurfaceChanged()} method, which provides you with the size of the canvas.</p>
    217 
    218 <p>To analyze the performance of your watch face, use the Android Device Monitor. In particular,
    219 ensure that the execution time for your
    220 <a href="{@docRoot}reference/android/support/wearable/watchface/CanvasWatchFaceService.Engine.html#onDraw(android.graphics.Canvas, android.graphics.Rect)"><code>Engine.onDraw()</code></a>
    221 implementation is short and
    222 consistent across invocations. For more information, see
    223 <a href="{@docRoot}tools/debugging/ddms.html">Using DDMS</a>.</p>
    224 
    225