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<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. 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@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@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@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@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@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@Override 353public void onEnterAmbient(Bundle ambientDetails) { 354 super.onEnterAmbient(ambientDetails); 355 356 refreshDisplayAndSetNextUpdate(); 357} 358 359@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@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@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<uses-library android:name="com.google.android.wearable" android:required="true" /> 411</pre> 412