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}studio/intro/update.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<application> 92 <uses-library android:name="com.google.android.wearable" 93 android:required="false" /> 94 ... 95</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<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@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. 144 To ease a user into the transition from interactive to ambient mode, try to maintain similar 145 placement of items on the screen. For more information on presenting content on an ambient screen, 146 see the 147<a href="{@docRoot}design/wear/watchfaces.html#DisplayModes">Watch Faces for Android Wear</a> 148design guide.</p> 149<p> Note that when your app runs on a device without a hardware button, palming the screen does not 150switch an app into ambient mode. Rather, it causes the app to exit and the home screen to appear. 151This behavior is intended to ensure that users can exit apps gracefully. However, these devices still 152 go to ambient mode when the screen times out. 153</p> 154 155<p class="note"><b>Note:</b> In ambient mode, disable any interactive elements on the 156screen, such as buttons. For more information on how to design user interactions for an always-on 157app, see the 158<a href="{@docRoot}design/wear/structure.html#AlwaysOn">App Structure for Android Wear</a> design 159guide. 160</p> 161 162<p>When the activity switches to ambient mode, the system calls the 163<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onEnterAmbient(android.os.Bundle)"><code>onEnterAmbient()</code></a> 164method in your wearable activity. The following code snippet shows how to change the text color to 165white and disable anti-aliasing after the system switches to ambient mode: 166</p> 167 168<pre> 169@Override 170public void onEnterAmbient(Bundle ambientDetails) { 171 super.onEnterAmbient(ambientDetails); 172 173 mStateTextView.setTextColor(Color.WHITE); 174 mStateTextView.getPaint().setAntiAlias(false); 175} 176</pre> 177 178<p>When the user taps the screen or brings up their wrist, the activity switches from ambient mode 179to interactive mode. The system calls the 180<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onExitAmbient()"><code>onExitAmbient()</code></a> 181method. Override this method to update the UI layout so that your app displays in a full-color, 182interactive state.</p> 183 184<p>The following code snippet shows how to change the text color to green and enable anti-aliasing 185when the system switches to interactive mode:</p> 186 187<pre> 188@Override 189public void onExitAmbient() { 190 super.onExitAmbient(); 191 192 mStateTextView.setTextColor(Color.GREEN); 193 mStateTextView.getPaint().setAntiAlias(true); 194} 195</pre> 196 197<h2 id="UpdateContent">Update Content in Ambient Mode</h2> 198 199<p>Ambient mode allows you to update the screen with new information for the user, but you must 200carefully balance display updates against the battery life. You should strongly consider only 201overriding the 202<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onUpdateAmbient()"><code>onUpdateAmbient()</code></a> 203method to update the screen once a minute in ambient mode. If your app requires more frequent 204updates, take into consideration that there is a trade-off between battery life and the frequency of 205updates. To realize battery savings, updates should be no more than once every 10 seconds. In 206practice, however, you should update your app less frequently than that. 207</p> 208 209<h3 id="StandardRefresh">Update once a minute</h3> 210 211<p>In order to preserve battery power, most wear apps should not frequently update the screen while 212in ambient mode. We recommend designing your app to update the screen once per minute while 213in this mode. The system provides a callback method, 214<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onUpdateAmbient()"><code>onUpdateAmbient()</code></a>, 215that allows you to update the screen at this recommended frequency.</p> 216 217<p>To update your app content, override the 218<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onUpdateAmbient()"><code>onUpdateAmbient()</code></a> 219method in your wearable activity: 220</p> 221 222<pre> 223@Override 224public void onUpdateAmbient() { 225 super.onUpdateAmbient(); 226 227 // Update the content 228} 229</pre> 230 231<h3 id="CustomRefresh">Update more frequently</h3> 232 233<p>For apps that require more frequent updates, such as a fitness, time-keeping, and travel 234information apps, use an 235<a href="{@docRoot}reference/android/app/AlarmManager.html"><code>AlarmManager</code></a> 236object to wake the processor and update the screen more frequently.</p> 237 238<p>To implement an alarm that updates content more frequently in ambient mode, follow these steps: 239</p> 240 241<ol> 242 <li>Prepare the alarm manager.</li> 243 <li>Set the frequency of the updates.</li> 244 <li>Schedule the next update when the activity switches to ambient mode or is currently in ambient 245 mode.</li> 246 <li>Cancel the alarm when the activity switches to interactive mode or the activity is stopped 247 </li> 248</ol> 249 250<p class="note"><b>Note:</b> The alarm manager may create new instances of your activity as they are 251triggered. To prevent this situation, ensure that your activity is declared with the 252<code>android:launchMode="singleInstance"</code> parameter in the manifest.</p> 253 254<p>The following sections describe these steps in detail.</p> 255 256<h4 id="PrepareAlarm">Prepare the alarm manager</h4> 257 258<p>The alarm manager launches a pending intent that updates the screen and schedules the next alarm. 259The following example shows how to declare the alarm manager and the pending intent in the 260<a href="{@docRoot}reference/android/app/Activity.html#onCreate(android.os.Bundle)"><code>onCreate()</code></a> 261method of your activity:</p> 262 263<pre> 264private AlarmManager mAmbientStateAlarmManager; 265private PendingIntent mAmbientStatePendingIntent; 266 267@Override 268public void onCreate(Bundle savedInstanceState) { 269 super.onCreate(savedInstanceState); 270 271 setAmbientEnabled(); 272 273 mAmbientStateAlarmManager = 274 (AlarmManager) getSystemService(Context.ALARM_SERVICE); 275 Intent ambientStateIntent = 276 new Intent(getApplicationContext(), MainActivity.class); 277 278 mAmbientStatePendingIntent = PendingIntent.getActivity( 279 getApplicationContext(), 280 0, 281 ambientStateIntent, 282 PendingIntent.FLAG_UPDATE_CURRENT); 283 ... 284} 285</pre> 286 287<p>When the alarm triggers and launches the pending intent, update the screen and schedule the next 288alarm by overriding the 289<a href="{@docRoot}reference/android/app/Activity.html#onNewIntent(android.content.Intent)"><code>onNewIntent()</code></a> 290method: 291</p> 292 293<pre> 294@Override 295public void onNewIntent(Intent intent) { 296 super.onNewIntent(intent); 297 298 setIntent(intent); 299 300 // Described in the following section 301 refreshDisplayAndSetNextUpdate(); 302} 303</pre> 304 305<h4 id="ScheduleUpdates">Update screen and schedule data updates</h4> 306 307<p>In this example activity, the alarm manager triggers every 20 seconds in ambient mode. When 308the timer ticks, the alarm triggers the intent to update the screen and then sets the delay for the 309next update. 310</p> 311 312<p>The following example shows how to update information on the screen and set the alarm for the 313next update: 314</p> 315 316<pre> 317// Milliseconds between waking processor/screen for updates 318private static final long AMBIENT_INTERVAL_MS = TimeUnit.SECONDS.toMillis(20); 319 320private void refreshDisplayAndSetNextUpdate() { 321 322 if (isAmbient()) { 323 // Implement data retrieval and update the screen for ambient mode 324 } else { 325 // Implement data retrieval and update the screen for interactive mode 326 } 327 328 long timeMs = System.currentTimeMillis(); 329 330 // Schedule a new alarm 331 if (isAmbient()) { 332 // Calculate the next trigger time 333 long delayMs = AMBIENT_INTERVAL_MS - (timeMs % AMBIENT_INTERVAL_MS); 334 long triggerTimeMs = timeMs + delayMs; 335 336 mAmbientStateAlarmManager.setExact( 337 AlarmManager.RTC_WAKEUP, 338 triggerTimeMs, 339 mAmbientStatePendingIntent); 340 341 } else { 342 // Calculate the next trigger time for interactive mode 343 } 344} 345</pre> 346 347<h4 id="ScheduleNext">Schedule the next alarm</h4> 348 349<p>Schedule the alarm to update the screen when the activity is entering ambient mode or when the 350activity is already in ambient mode by overriding the 351<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onEnterAmbient(android.os.Bundle)"><code>onEnterAmbient()</code></a> 352method and the 353<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onUpdateAmbient()"><code>onUpdateAmbient()</code></a> 354method:</p> 355 356<pre> 357@Override 358public void onEnterAmbient(Bundle ambientDetails) { 359 super.onEnterAmbient(ambientDetails); 360 361 refreshDisplayAndSetNextUpdate(); 362} 363 364@Override 365public void onUpdateAmbient() { 366 super.onUpdateAmbient(); 367 368 refreshDisplayAndSetNextUpdate(); 369} 370</pre> 371 372<p class="note"><b>Note:</b> In this example, the <code>refreshDisplayAndSetNextUpdate()</code> 373method is called whenever the screen needs to be updated. For more examples of when to call this 374method, see the <a href="{@docRoot}samples/AlwaysOn/index.html">AlwaysOn</a> sample. 375</p> 376 377<h4 id="CancelAlarm">Cancel the alarm</h4> 378 379<p>When the device switches to interactive mode, cancel the alarm in the 380<a href="{@docRoot}reference/android/support/wearable/activity/WearableActivity.html#onExitAmbient()"><code>onExitAmbient()</code></a> 381method:</p> 382 383<pre> 384@Override 385public void onExitAmbient() { 386 super.onExitAmbient(); 387 388 mAmbientStateAlarmManager.cancel(mAmbientStatePendingIntent); 389} 390</pre> 391 392<p>When the user exits or stops your activity, cancel the alarm in the 393<a href="{@docRoot}reference/android/app/Activity.html#onDestroy()"><code>onDestroy()</code></a> 394method of your activity:</p> 395 396<pre> 397@Override 398public void onDestroy() { 399 mAmbientStateAlarmManager.cancel(mAmbientStatePendingIntent); 400 super.onDestroy(); 401} 402</pre> 403 404<h2 id="BackwardCompatibility">Maintain Backward-compatibility</h2> 405 406<p>Activities that support ambient mode automatically fall back to normal activities on Wear devices 407that are on Android versions prior to 5.1 (API level 22). No special app code is required to support 408devices on these versions of Android. When the device switches to ambient mode, the device returns 409to the home screen and exits your activity.</p> 410 411<p>If your app should not be installed or updated on devices with Android versions prior to 5.1, 412update your manifest with the following:</p> 413 414<pre> 415<uses-library android:name="com.google.android.wearable" android:required="true" /> 416</pre> 417