1page.title=Keeping Your App Visible
2page.tags=wear
3helpoutsWidget=true
4
5@jd:body
6
7<div id="tb-wrapper">
8<div id="tb">
9<h2>This lesson teaches you to</h2>
10<ol>
11  <li><a href="#EnableAmbient">Enable Ambient Mode in a Wearable App</a></li>
12  <li><a href="#UpdateContent">Update Content in Ambient Mode</a></li>
13  <li><a href="#BackwardCompatibility">Maintain Backward-compatibility</a></li>
14</ol>
15<h2>You should also read</h2>
16  <ul>
17    <li><a href="{@docRoot}design/wear/structure.html">App Structure for Android Wear</a></li>
18  </ul>
19<h2>Related Samples</h2>
20  <ul>
21    <li><a href="{@docRoot}samples/AlwaysOn/index.html">AlwaysOn</a></li>
22  </ul>
23</div>
24</div>
25
26<p>Some Wear apps are most useful when they are constantly visible to the user. For example, users
27out on a run can glance at their wearable to see the distance covered and time elapsed, or after
28recording a grocery list on their wearable, users can quickly see which items are remaining on the
29list as they shop at the market. Making an app constantly visible has an impact on battery life,
30so you should carefully consider that impact when adding this feature to your app.
31</p>
32
33<div class="video-wrapper-left">
34<iframe src="https://www.youtube.com/embed/7m6Z9d0fDaM" frameborder="0"
35allowfullscreen></iframe>
36</div>
37
38<p>Android Wear devices running Android version 5.1 or higher allow apps to remain in the
39foreground while saving battery power. Android Wear apps can control what’s displayed on the
40wearable device screen while the device is in a low-power ambient mode. Wear apps that run in both
41ambient and interactive mode are called <i>always-on</i> apps.
42</p>
43
44<p>This lesson describes how to enable your wearable app to be always-on, update the screen
45while in ambient mode, and maintain backwards compatibility.
46</p>
47
48<h2 id="EnableAmbient">Enable Ambient Mode in a Wearable App</h2>
49
50<p>For new and existing projects, you can add ambient mode support to your Wear app by updating
51your development project configuration. After you complete the project configuration, extend the
52<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html"><code>WearableActivity</code></a>
53class, which provides all the methods you need to enable ambient mode in your app. The following
54sections describe these steps in detail.</p>
55
56<h3 id="ConfigureProject">Configure your development project</h3>
57
58<p>In order to support ambient mode in your Wear app, you must update your Android SDK and configure
59your development project. Follow these steps to make the necessary changes:</p>
60
61<ul>
62  <li>Update your SDK to include the Android 5.1 (API 22) or higher platform, which provides the
63  APIs to allow activities to go into ambient mode. For more information on how to update your SDK,
64  see
65  <a href="{@docRoot}sdk/installing/adding-packages.html#GetTools">Adding SDK Packages</a>.
66  </li>
67  <li> Create a project or modify an existing project to target Android 5.1 or higher. This means
68  you must set the manifest
69  <a href="{@docRoot}topics/manifest/uses-sdk-element.html"><code>targetSdkVersion</code></a> to 22
70  or higher.</li>
71  <li>Set the manifest
72  <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>minSdkVersion</code></a> to
73  20 or higher, if you want to support devices on versions prior to Android 5.1. For more
74  information on backwards compatibility, see
75  <a href="#BackwardCompatibility">Maintain Backward-compatibility</a>.</li>
76  </li>
77  <li>Add or update the following dependencies to your <code>build.gradle</code> file:
78<pre>
79dependencies {
80    ...
81    compile 'com.google.android.support:wearable:1.2.0'
82    provided 'com.google.android.wearable:wearable:1.0.0'
83}
84</pre>
85<p class="note"><b>Note:</b> The <code>provided</code> dependency ensures that the classes loaded at
86run-time to support ambient mode are also available at compile-time.
87</p>
88</li>
89  <li>Add the wearable shared library entry into the wearable app manifest:
90<pre>
91&lt;application>
92  &lt;uses-library android:name="com.google.android.wearable"
93                android:required="false" />
94  ...
95&lt;/application>
96</pre>
97  </li>
98  <li>Add the
99  <a href="{@docRoot}reference/android/Manifest.permission.html#WAKE_LOCK"><code>WAKE_LOCK</code></a>
100  permission to the handheld and wearable app manifest:
101<pre>
102&lt;uses-permission android:name="android.permission.WAKE_LOCK" />
103</pre>
104  </li>
105</ul>
106
107<h3 id="CreateActivity">Create an activity that supports ambient mode</h3>
108
109<p>To enable ambient mode in your activity, use the
110<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html"><code>WearableActivity</code></a>
111class and methods.
112</p>
113
114<ol>
115  <li>Create an activity that extends
116  <a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html"><code>WearableActivity</code></a>.</li>
117  <li>In the
118  <a href="{@docRoot}reference/android/app/Activity.html#onCreate(android.os.Bundle)"><code>onCreate()</code></a>
119  method of your activity, call the
120  <a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#setAmbientEnabled()"><code>setAmbientEnabled()</code></a>
121  method.</li>
122</ol>
123
124<p>Enable ambient mode in your activity as follows:</p>
125
126<pre>
127public class MainActivity extends WearableActivity {
128
129&#64;Override
130public void onCreate(Bundle savedInstanceState) {
131    super.onCreate(savedInstanceState);
132
133    <strong>setAmbientEnabled();</strong>
134    ...
135}
136</pre>
137
138<h3 id="EnableDisable">Handle transitions between modes</h3>
139
140<p>If the user does not interact with your app for a period of time while it is displayed, or if
141the user covers the screen with their palm, the system switches the activity to ambient mode.
142After the app switches to ambient mode, update the activity UI to a more basic layout to reduce
143power consumption. You should use a black background with minimal white graphics and text. To
144ease a user into the transition from interactive to ambient mode, try to maintain similar placement
145of items on the screen. For more information on presenting content on an ambient screen, see the
146<a href="{@docRoot}design/wear/watchfaces.html#DisplayModes">Watch Faces for Android Wear</a>
147design guide.
148</p>
149
150<p class="note"><b>Note:</b> In ambient mode, disable any interactive elements on the
151screen, such as buttons. For more information on how to design user interactions for an always-on
152app, see the
153<a href="{@docRoot}design/wear/structure.html#AlwaysOn">App Structure for Android Wear</a> design
154guide.
155</p>
156
157<p>When the activity switches to ambient mode, the system calls the
158<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onEnterAmbient(android.os.Bundle)"><code>onEnterAmbient()</code></a>
159method in your wearable activity. The following code snippet shows how to change the text color to
160white and disable anti-aliasing after the system switches to ambient mode:
161</p>
162
163<pre>
164&#64;Override
165public void onEnterAmbient(Bundle ambientDetails) {
166    super.onEnterAmbient(ambientDetails);
167
168    mStateTextView.setTextColor(Color.WHITE);
169    mStateTextView.getPaint().setAntiAlias(false);
170}
171</pre>
172
173<p>When the user taps the screen or brings up their wrist, the activity switches from ambient mode
174to interactive mode. The system calls the
175<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onExitAmbient()"><code>onExitAmbient()</code></a>
176method. Override this method to update the UI layout so that your app displays in a full-color,
177interactive state.</p>
178
179<p>The following code snippet shows how to change the text color to green and enable anti-aliasing
180when the system switches to interactive mode:</p>
181
182<pre>
183&#64;Override
184public void onExitAmbient() {
185    super.onExitAmbient();
186
187    mStateTextView.setTextColor(Color.GREEN);
188    mStateTextView.getPaint().setAntiAlias(true);
189}
190</pre>
191
192<h2 id="UpdateContent">Update Content in Ambient Mode</h2>
193
194<p>Ambient mode allows you to update the screen with new information for the user, but you must
195carefully balance display updates against the battery life. You should strongly consider only
196overriding the
197<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onUpdateAmbient()"><code>onUpdateAmbient()</code></a>
198method to update the screen once a minute in ambient mode. If your app requires more frequent
199updates, take into consideration that there is a trade-off between battery life and the frequency of
200updates. To realize battery savings, updates should be no more than once every 10 seconds. In
201practice, however, you should update your app less frequently than that.
202</p>
203
204<h3 id="StandardRefresh">Update once a minute</h3>
205
206<p>In order to preserve battery power, most wear apps should not frequently update the screen while
207in ambient mode. We recommend designing your app to update the screen once per minute while
208in this mode. The system provides a callback method,
209<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onUpdateAmbient()"><code>onUpdateAmbient()</code></a>,
210that allows you to update the screen at this recommended frequency.</p>
211
212<p>To update your app content, override the
213<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onUpdateAmbient()"><code>onUpdateAmbient()</code></a>
214method in your wearable activity:
215</p>
216
217<pre>
218&#64;Override
219public void onUpdateAmbient() {
220    super.onUpdateAmbient();
221
222    // Update the content
223}
224</pre>
225
226<h3 id="CustomRefresh">Update more frequently</h3>
227
228<p>For apps that require more frequent updates, such as a fitness, time-keeping, and travel
229information apps, use an
230<a href="{@docRoot}reference/android/app/AlarmManager.html"><code>AlarmManager</code></a>
231object to wake the processor and update the screen more frequently.</p>
232
233<p>To implement an alarm that updates content more frequently in ambient mode, follow these steps:
234</p>
235
236<ol>
237  <li>Prepare the alarm manager.</li>
238  <li>Set the frequency of the updates.</li>
239  <li>Schedule the next update when the activity switches to ambient mode or is currently in ambient
240      mode.</li>
241  <li>Cancel the alarm when the activity switches to interactive mode or the activity is stopped
242  </li>
243</ol>
244
245<p class="note"><b>Note:</b> The alarm manager may create new instances of your activity as they are
246triggered. To prevent this situation, ensure that your activity is declared with the
247<code>android:launchMode="singleInstance"</code> parameter in the manifest.</p>
248
249<p>The following sections describe these steps in detail.</p>
250
251<h4 id="PrepareAlarm">Prepare the alarm manager</h4>
252
253<p>The alarm manager launches a pending intent that updates the screen and schedules the next alarm.
254The following example shows how to declare the alarm manager and the pending intent in the
255<a href="{@docRoot}reference/android/app/Activity.html#onCreate(android.os.Bundle)"><code>onCreate()</code></a>
256method of your activity:</p>
257
258<pre>
259private AlarmManager mAmbientStateAlarmManager;
260private PendingIntent mAmbientStatePendingIntent;
261
262&#64;Override
263public void onCreate(Bundle savedInstanceState) {
264    super.onCreate(savedInstanceState);
265
266    setAmbientEnabled();
267
268    mAmbientStateAlarmManager =
269        (AlarmManager) getSystemService(Context.ALARM_SERVICE);
270    Intent ambientStateIntent =
271        new Intent(getApplicationContext(), MainActivity.class);
272
273    mAmbientStatePendingIntent = PendingIntent.getActivity(
274        getApplicationContext(),
275        0,
276        ambientStateIntent,
277        PendingIntent.FLAG_UPDATE_CURRENT);
278    ...
279}
280</pre>
281
282<p>When the alarm triggers and launches the pending intent, update the screen and schedule the next
283alarm by overriding the
284<a href="{@docRoot}reference/android/app/Activity.html#onNewIntent(android.content.Intent)"><code>onNewIntent()</code></a>
285method:
286</p>
287
288<pre>
289&#64;Override
290public void onNewIntent(Intent intent) {
291    super.onNewIntent(intent);
292
293    setIntent(intent);
294
295    // Described in the following section
296    refreshDisplayAndSetNextUpdate();
297}
298</pre>
299
300<h4 id="ScheduleUpdates">Update screen and schedule data updates</h4>
301
302<p>In this example activity, the alarm manager triggers every 20 seconds in ambient mode. When
303the timer ticks, the alarm triggers the intent to update the screen and then sets the delay for the
304next update.
305</p>
306
307<p>The following example shows how to update information on the screen and set the alarm for the
308next update:
309</p>
310
311<pre>
312// Milliseconds between waking processor/screen for updates
313private static final long AMBIENT_INTERVAL_MS = TimeUnit.SECONDS.toMillis(20);
314
315private void refreshDisplayAndSetNextUpdate() {
316
317    if (isAmbient()) {
318        // Implement data retrieval and update the screen for ambient mode
319    } else {
320        // Implement data retrieval and update the screen for interactive mode
321    }
322
323    long timeMs = System.currentTimeMillis();
324
325    // Schedule a new alarm
326    if (isAmbient()) {
327        // Calculate the next trigger time
328        long delayMs = AMBIENT_INTERVAL_MS - (timeMs % AMBIENT_INTERVAL_MS);
329        long triggerTimeMs = timeMs + delayMs;
330
331        mAmbientStateAlarmManager.setExact(
332            AlarmManager.RTC_WAKEUP,
333            triggerTimeMs,
334            mAmbientStatePendingIntent);
335
336    } else {
337        // Calculate the next trigger time for interactive mode
338    }
339}
340</pre>
341
342<h4 id="ScheduleNext">Schedule the next alarm</h4>
343
344<p>Schedule the alarm to update the screen when the activity is entering ambient mode or when the
345activity is already in ambient mode by overriding the
346<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onEnterAmbient(android.os.Bundle)"><code>onEnterAmbient()</code></a>
347method and the
348<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onUpdateAmbient()"><code>onUpdateAmbient()</code></a>
349method:</p>
350
351<pre>
352&#64;Override
353public void onEnterAmbient(Bundle ambientDetails) {
354    super.onEnterAmbient(ambientDetails);
355
356    refreshDisplayAndSetNextUpdate();
357}
358
359&#64;Override
360public void onUpdateAmbient() {
361    super.onUpdateAmbient();
362
363    refreshDisplayAndSetNextUpdate();
364}
365</pre>
366
367<p class="note"><b>Note:</b> In this example, the <code>refreshDisplayAndSetNextUpdate()</code>
368method is called whenever the screen needs to be updated. For more examples of when to call this
369method, see the <a href="{@docRoot}samples/AlwaysOn/index.html">AlwaysOn</a> sample.
370</p>
371
372<h4 id="CancelAlarm">Cancel the alarm</h4>
373
374<p>When the device switches to interactive mode, cancel the alarm in the
375<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onExitAmbient()"><code>onExitAmbient()</code></a>
376method:</p>
377
378<pre>
379&#64;Override
380public void onExitAmbient() {
381    super.onExitAmbient();
382
383    mAmbientStateAlarmManager.cancel(mAmbientStatePendingIntent);
384}
385</pre>
386
387<p>When the user exits or stops your activity, cancel the alarm in the
388<a href="{@docRoot}reference/android/app/Activity.html#onDestroy()"><code>onDestroy()</code></a>
389method of your activity:</p>
390
391<pre>
392&#64;Override
393public void onDestroy() {
394    mAmbientStateAlarmManager.cancel(mAmbientStatePendingIntent);
395    super.onDestroy();
396}
397</pre>
398
399<h2 id="BackwardCompatibility">Maintain Backward-compatibility</h2>
400
401<p>Activities that support ambient mode automatically fall back to normal activities on Wear devices
402that are on Android versions prior to 5.1 (API level 22). No special app code is required to support
403devices on these versions of Android. When the device switches to ambient mode, the device returns
404to the home screen and exits your activity.</p>
405
406<p>If your app should not be installed or updated on devices with Android versions prior to 5.1,
407update your manifest with the following:</p>
408
409<pre>
410&lt;uses-library android:name="com.google.android.wearable" android:required="true" />
411</pre>
412