• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.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">
20Making a performant watch face</a></li>
21  <li><a href="http://android-developers.blogspot.com/2016/04/deprecation-of-bindlistener.html">
22Deprecation 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.
28A watch face runs continuously, so it must use power
29efficiently. </p>
30
31<p>Services must not perform unnecessary computations.
32Watch faces with animations must run smoothly while accommodating
33notification 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
38periods 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
43computations only when active; use callbacks
44in <a href="{@docRoot}reference/android/support/wearable/watchface/
45WatchFaceService.Engine.html">{@code WatchFaceService.Engine}</a>.
46Preferably, use the following methods of that class to determine if
47the 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/
56WatchFaceService.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
66with <a href="https://developers.google.com/android/reference/com/google/
67android/gms/wearable/DataApi.html#addListener
68(com.google.android.gms.common.api.GoogleApiClient, com.
69google.android.gms.wearable.DataApi.DataListener)">{@code DataApi.addListener}</a>.
70For an example, see <a href="{@docRoot}training/wearables/data-layer/
71data-items.html#ListenEvents">Syncing Data Items</a>.</p>
72
73<p>Do not use <a href="https://developers.google.com/
74android/reference/com/google/android/gms/wearable/
75WearableListenerService">{@code WearableListenerService}</a> to listen for
76events, because it is
77called whether or not a watch face is active. For more information, see
78<a href="http://android-developers.blogspot.com/2016/04/
79deprecation-of-bindlistener.html">Deprecation of BIND_LISTENER
80with Android Wear APIs</a>.</p>
81
82<p>Do not register a broadcast receiver in the Android manifest file
83to get system events such as time zone changes, battery events, etc., because
84the <a href="{@docRoot}reference/android/content/BroadcastReceiver.html">{@code BroadcastReceiver}</a>
85is 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.
87content.BroadcastReceiver, android.content.IntentFilter)">{@code registerReceiver}</a> method
88of 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">
93Android Wear companion app</a> enables developers and users to see how much battery
94is consumed by different processes
95on the wearable device (under <strong>Settings</strong> > <strong>Watch
96battery</strong>).</p>
97
98<p>For information about features introduced in Android 5.0 that help you improve battery life,
99see <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
108animations look fluid at 30 frames per second, so you should avoid running your animations
109at 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
114face should let the CPU sleep in between animations. For example, you can use short bursts of
115animation every second in interactive mode and then let the CPU sleep until the next second.
116Letting 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
119every 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
124and overlapped on top of the background image, such as clock hands and other elements of the design
125that 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>
127method 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
129Face</a>.</p>
130
131<p>The larger these graphic assets are, the more computationally expensive it is to transform them.
132Transforming 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>
134method 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
153by 97&#37;.</p>
154
155<p>Reducing the size of your bitmap assets as described in this section not only improves
156the 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
161graphic asset. You can often combine the background image in interactive mode with the tick
162marks 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
167android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint)
168Canvas.drawBitmap()} method, you can provide a {@link android.graphics.Paint} instance to configure
169several options. To improve performance, disable anti-aliasing using the {@link
170android.graphics.Paint#setAntiAlias setAntiAlias()} method, since this option does not have any
171effect 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
179enabled (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
186setFilterBitmap()} method. <a href="#fig2">Figure 2</a> shows a magnified view of a clock hand with
187and without bitmap filtering.</p>
188
189<p class="note"><strong>Note:</strong> In low-bit ambient mode, the system does not reliably
190render the colors in the image for bitmap filtering to process successfully. When ambient mode is
191active, 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>
197method every time it redraws your watch face, so you should only include operations that are
198strictly 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>
202method:</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>
213method instead.
214You can resize images ahead of time in the {@link
215android.service.wallpaper.WallpaperService.Engine#onSurfaceChanged(android.view.SurfaceHolder, int, int, int)
216Engine.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,
219ensure 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>
221implementation is short and
222consistent across invocations. For more information, see
223<a href="{@docRoot}tools/debugging/ddms.html">Using DDMS</a>.</p>
224
225