1 page.title=Handling TV Hardware 2 page.tags="unsupported" 3 trainingnavtop=true 4 5 @jd:body 6 7 <div id="tb-wrapper"> 8 <div id="tb"> 9 <h2>This lesson teaches you how to</h2> 10 <ol> 11 <li><a href="#runtime-check">Check for a TV Device</a> 12 <li><a href="#handle-features">Handle Unsupported Hardware Features</a></li> 13 <li><a href="#controllers">Manage Hardware Controllers</a> 14 </li> 15 </ol> 16 </div> 17 </div> 18 19 <p> 20 TV hardware is substantially different from other Android devices. TVs do not 21 include some of the hardware features found on other Android devices, such as touch screens, 22 cameras, and GPS receivers. TVs are also completely dependent on secondary hardware devices. 23 In order for users to interact with TV apps, they must use a remote control or game pad. When 24 you build an app for TV, you must carefully consider the hardware limitations and requirements of 25 operating on TV hardware. 26 </p> 27 28 <p> 29 This lesson discusses how to check if your app is running on a TV, how to handle unsupported 30 hardware features, and discusses the requirements for handling controllers for TV devices. 31 </p> 32 33 34 <h2 id="runtime-check">Check for a TV Device</h2> 35 36 <p> 37 If you are building an app that operates both on TV devices and other devices, you may need to 38 check what kind of device your app is running on and adjust the operation of your app. For 39 instance, if you have an app that can be started through an {@link android.content.Intent}, your 40 application should check the device properties to determine if it should start a TV-oriented 41 activity or a phone activity. 42 </p> 43 44 <p> 45 The recommended way to determine if your app is running on a TV device is to use the {@link 46 android.app.UiModeManager#getCurrentModeType UiModeManager.getCurrentModeType()} method to check 47 if the device is running in television mode. The following example code shows you how to check if 48 your app is running on a TV device: 49 </p> 50 51 <pre> 52 public static final String TAG = "DeviceTypeRuntimeCheck"; 53 54 UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE); 55 if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) { 56 Log.d(TAG, "Running on a TV Device") 57 } else { 58 Log.d(TAG, "Running on a non-TV Device") 59 } 60 </pre> 61 62 63 <h2 id="handle-features">Handle Unsupported Hardware Features</h2> 64 65 <p> 66 Depending on the design and functionality of your app, you may be able to work around certain 67 hardware features being unavailable. This section discusses what hardware features are typically 68 not available for TV, how to detect missing hardware features, and suggests alternatives to 69 using these features. 70 </p> 71 72 73 <h3 id="unsupported-features">Unsupported TV hardware features</h3> 74 75 <p> 76 TVs have a different purpose from other devices, and so they do not have hardware features that 77 other Android-powered devices often have. For this reason, the Android system does not support 78 the following features for a TV device: 79 </p> 80 81 <table> 82 <tr> 83 <th>Hardware</th> 84 <th>Android feature descriptor</th> 85 </tr> 86 <tr> 87 <td>Touchscreen</td> 88 <td>{@code android.hardware.touchscreen}</td> 89 </tr> 90 <tr> 91 <td>Touchscreen emulator</td> 92 <td>{@code android.hardware.faketouch}</td> 93 </tr> 94 <tr> 95 <td>Telephony</td> 96 <td>{@code android.hardware.telephony}</td> 97 </tr> 98 <tr> 99 <td>Camera</td> 100 <td>{@code android.hardware.camera}</td> 101 </tr> 102 <tr> 103 <td>Bluetooth</td> 104 <td>{@code android.hardware.bluetooth}</td> 105 </tr> 106 <tr> 107 <td>Near Field Communications (NFC)</td> 108 <td>{@code android.hardware.nfc}</td> 109 </tr> 110 <tr> 111 <td>GPS</td> 112 <td>{@code android.hardware.location.gps}</td> 113 </tr> 114 <tr> 115 <td>Microphone <sup><a href="#cont-mic">[1]</a></sup></td> 116 <td>{@code android.hardware.microphone}</td> 117 </tr> 118 <tr> 119 <td>Sensors</td> 120 <td>{@code android.hardware.sensor}</td> 121 </tr> 122 </table> 123 124 <p id="cont-mic" class="note"> 125 <strong>[1]</strong> Some TV controllers have a microphone, which is 126 not the same as the microphone hardware feature described here. The controller microphone is fully 127 supported. 128 </p> 129 130 <p> 131 See the <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#features-reference"> 132 Features Reference</a> for a complete list of features, subfeatures, and their descriptors. 133 </p> 134 135 136 <h3 id="declare-hardware-requirements">Declaring hardware requirements for TV</h3> 137 138 <p> 139 Android apps can declare hardware feature requirements in the app manifest to ensure that they do 140 not get installed on devices that do not provide those features. If you are extending an existing 141 app for use on TV, closely review your app's manifest for any hardware requirement 142 declarations that might prevent it from being installed on a TV device. 143 </p> 144 145 <p> 146 If your app uses hardware features (such as a touchscreen or camera) that are not available on 147 TV, but can operate without the use of those features, modify your app's manifest to 148 indicate that these features are not required by your app. The following manifest code snippet 149 demonstrates how to declare that your app does not require hardware features which are unavailable 150 on TV devices, even though your app may use these features on non-TV devices: 151 </p> 152 153 <pre> 154 <uses-feature android:name="android.hardware.touchscreen" 155 android:required="false"/> 156 <uses-feature android:name="android.hardware.faketouch" 157 android:required="false"/> 158 <uses-feature android:name="android.hardware.telephony" 159 android:required="false"/> 160 <uses-feature android:name="android.hardware.camera" 161 android:required="false"/> 162 <uses-feature android:name="android.hardware.bluetooth" 163 android:required="false"/> 164 <uses-feature android:name="android.hardware.nfc" 165 android:required="false"/> 166 <uses-feature android:name="android.hardware.gps" 167 android:required="false"/> 168 <uses-feature android:name="android.hardware.microphone" 169 android:required="false"/> 170 <uses-feature android:name="android.hardware.sensor" 171 android:required="false"/> 172 </pre> 173 174 <p class="note"><strong>Note:</strong> Some features have subfeatures like {@code android.hardware.camera.front}, 175 as described in the <a href="guide/topics/manifest/uses-feature-element.html#features-reference"> 176 Feature Reference</a>. Be sure to mark as {@code required="false"} any subfeatures also used in 177 your app.</p> 178 179 <p> 180 All apps intended for use on TV devices must declare that the touch screen feature is not required 181 as described in <a href="{@docRoot}training/tv/start/start.html#no-touchscreen">Get Started with 182 TV Apps</a>. If your app normally uses one or more of the features listed above, change the 183 {@code android:required} attribute setting to {@code false} for those features in your manifest. 184 </p> 185 186 <p class="caution"> 187 <strong>Caution:</strong> Declaring a hardware feature as required by setting its 188 value to {@code true} prevents your app from being installed on TV 189 devices or appearing in the Android TV home screen launcher. 190 </p> 191 192 <p> 193 Once you decide to make hardware features optional for your app, you must check for the 194 availability of those features at runtime and then adjust your app's behavior. The next section 195 discusses how to check for hardware features and suggests some approaches for changing the 196 behavior of your app. 197 </p> 198 199 <p> 200 For more information on filtering and declaring features in the manifest, see the 201 <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code uses-feature}</a> 202 guide. 203 </p> 204 205 206 <h3 id="hardware-permissions">Declaring permissions that imply hardware features</h3> 207 208 <p> 209 Some <a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">{@code uses-permission}</a> 210 manifest declarations <em>imply hardware features</em>. This behavior means that requesting some 211 permissions in your app manifest can exclude your app from from being installed and used on TV 212 devices. The following commonly requested permissions create an implicit hardware feature 213 requirement: 214 </p> 215 216 <table> 217 <tr> 218 <th>Permission</th> 219 <th>Implied hardware feature</th> 220 </tr> 221 <tr> 222 <td>{@link android.Manifest.permission#RECORD_AUDIO}</td> 223 <td>{@code android.hardware.microphone}</td> 224 </tr> 225 <tr> 226 <td>{@link android.Manifest.permission#CAMERA}</td> 227 <td>{@code android.hardware.camera} <em>and</em> <br> 228 {@code android.hardware.camera.autofocus}</td> 229 </tr> 230 <tr> 231 <td>{@link android.Manifest.permission#ACCESS_COARSE_LOCATION}</td> 232 <td>{@code android.hardware.location} <em>and</em> <br> 233 {@code android.hardware.location.network}</td> 234 </tr> 235 <tr> 236 <td>{@link android.Manifest.permission#ACCESS_FINE_LOCATION}</td> 237 <td>{@code android.hardware.location} <em>and</em> <br> 238 {@code android.hardware.location.gps}</td> 239 </tr> 240 </table> 241 242 <p> 243 For a complete list of permission requests that imply a hardware feature requirement, see the 244 <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#permissions-features">{@code 245 uses-feature}</a> guide. If your app requests one of the features listed above, include a 246 <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code uses-feature}</a> 247 declaration in your manifest for the implied hardware feature that indicates it is not 248 required ({@code android:required="false"}). 249 </p> 250 251 252 <h3 id="check-features">Checking for hardware features</h2> 253 254 <p> 255 The Android framework can tell you if hardware features are not available on the device where 256 your app is running. Use the {@link android.content.pm.PackageManager#hasSystemFeature(String)} 257 method to check for specific features at runtime. This method takes a single string argument that 258 specifies the feature you want to check. 259 </p> 260 261 <p>The following code example demonstrates how to detect the availability of hardware features 262 at runtime:</p> 263 264 <pre> 265 // Check if the telephony hardware feature is available. 266 if (getPackageManager().hasSystemFeature("android.hardware.telephony")) { 267 Log.d("HardwareFeatureTest", "Device can make phone calls"); 268 } 269 270 // Check if android.hardware.touchscreen feature is available. 271 if (getPackageManager().hasSystemFeature("android.hardware.touchscreen")) { 272 Log.d("HardwareFeatureTest", "Device has a touch screen."); 273 } 274 </pre> 275 276 277 <h4 id="no-touchscreen">Touch screen</h4> 278 279 <p> 280 Since most TVs do not have touch screens, Android does not support touch screen interaction for 281 TV devices. Furthermore, using a touch screen is not consistent with a viewing environment where 282 the user is seated 10 feet away from the display. Make sure that your UI elements and text do not 283 require or imply the use of a touchscreen. 284 </p> 285 286 <p> 287 On TV devices, you should design your app to work with this interaction model by supporting 288 navigation using a directional pad (D-pad) on a TV remote control. For more information on 289 properly supporting navigation using TV-friendly controls, see 290 <a href="{@docRoot}training/tv/start/navigation.html">Creating TV Navigation</a>. 291 </p> 292 293 294 <h4 id="no-camera">Camera</h4> 295 296 <p> 297 Although a TV typically does not have a camera, you can still provide a photography-related 298 app on a TV. For example, if you have an app that takes, views, and edits photos, you can 299 disable its picture-taking functionality for TVs and still allow users to view and even edit 300 photos. If you decide to enable your camera-related app to work on a TV, add the 301 following feature declaration your app manifest: 302 </p> 303 304 <pre> 305 <uses-feature android:name="android.hardware.camera" android:required="false" /> 306 </pre> 307 308 <p> 309 If you enable your app to run without a camera, add code to your app 310 that detects if the camera feature is available and makes adjustments to the operation of your 311 app. The following code example demonstrates how to detect the presence of a camera: 312 </p> 313 314 <pre> 315 // Check if the camera hardware feature is available. 316 if (getPackageManager().hasSystemFeature("android.hardware.camera")) { 317 Log.d("Camera test", "Camera available!"); 318 } else { 319 Log.d("Camera test", "No camera available. View and edit features only."); 320 } 321 </pre> 322 323 324 <h4 id="no-gps">GPS</h4> 325 326 <p> 327 TVs are stationary, indoor devices, and do not have built-in global positioning system (GPS) 328 receivers. If your app uses location information, you can still allow users to search for 329 a location, or use a static location provider such as a zip code configured during the TV device 330 setup. 331 </p> 332 333 <pre> 334 // Request a static location from the location manager 335 LocationManager locationManager = (LocationManager) this.getSystemService( 336 Context.LOCATION_SERVICE); 337 Location location = locationManager.getLastKnownLocation("static"); 338 339 // Attempt to get postal or zip code from the static location object 340 Geocoder geocoder = new Geocoder(this); 341 Address address = null; 342 try { 343 address = geocoder.getFromLocation(location.getLatitude(), 344 location.getLongitude(), 1).get(0); 345 Log.d("Zip code", address.getPostalCode()); 346 347 } catch (IOException e) { 348 Log.e(TAG, "Geocoder error", e); 349 } 350 </pre> 351 352 353 <h2 id="controllers">Handling Controllers</h2> 354 355 <p> 356 TV devices require a secondary hardware device for interacting with apps, in the form of a basic 357 remote controller or game controller. This means that your app must support D-pad input. It also 358 means that your app may need to handle controllers going offline and input from more than one 359 type of controller. 360 </p> 361 362 363 <h3 id="d-pad-minimum">D-pad minimum controls</h3> 364 365 <p> 366 The default controller for a TV device is a D-pad. In general, your app should be operable from a 367 remote controller that only has up, down, left, right, select, Back, and Home buttons. If your app 368 is a game that typically requires a game controller with additional controls, your app should 369 attempt to allow gameplay with these D-pad controls. In this case, your app should also warn the 370 user that 371 a controller is required and allow them to exit your game gracefully using the D-pad controller. 372 For more information about handling navigation with D-pad controller for TV devices, see 373 <a href="{@docRoot}training/tv/start/navigation.html">Creating TV Navigation</a>. 374 </p> 375 376 377 <h3 id="controller-disconnects">Handle controller disconnects</h3> 378 379 <p> 380 Controllers for TV are frequently Bluetooth devices which may attempt to save power by periodically 381 going into sleep mode and disconnecting from the TV device. This means that an app might be 382 interrupted or restarted if it is not configured to handle these reconnect events. These events 383 can happen in any of the following circumstances: 384 </p> 385 386 <ul> 387 <li>While watching a video which is several minutes long, a D-Pad or game controller goes into 388 sleep mode, disconnects from the TV device and then reconnects later on. 389 </li> 390 <li>During gameplay, a new player joins the game using a game controller that is not currently 391 connected. 392 </li> 393 <li>During gameplay, a player leaves the game and disconnects a game controller. 394 </li> 395 </ul> 396 397 <p> 398 Any TV app activity that is subject to disconnect and reconnect events must be configured to 399 handle reconnection events in the app manifest. The following code sample demonstrates how to 400 enable an activity to handle configuration changes, including a keyboard or navigation device 401 connecting, disconnecting, or reconnecting: 402 </p> 403 404 <pre> 405 <activity 406 android:name="com.example.android.TvActivity" 407 android:label="@string/app_name" 408 <strong>android:configChanges="keyboard|keyboardHidden|navigation"</strong> 409 android:theme="@style/Theme.Leanback"> 410 411 <intent-filter> 412 <action android:name="android.intent.action.MAIN" /> 413 <category android:name="android.intent.category.LEANBACK_LAUNCHER" /> 414 </intent-filter> 415 ... 416 </activity> 417 </pre> 418 419 <p> 420 This configuration change allows the app to continue running through a reconnection event, rather 421 than being restarted by the Android framework, which is not a good user experience. 422 </p> 423 424 425 <h3 id="d-pad-variants">Handle D-pad input variations</h3> 426 427 <p> 428 TV device users may have more than one type of controller that they use with their TV. For 429 example, a user might have both a basic D-pad controller and a game controller. The key codes 430 provided by a game controller when it is being used for D-pad functions may vary from the key 431 codes sent by a physical D-pad. 432 </p> 433 434 <p> 435 Your app should handle the variations of D-pad input from a game controller, so the user does not 436 have to physically switch controllers to operate your app. For more information on handling these 437 input variations, see <a href="{@docRoot}training/game-controllers/controller-input.html#dpad"> 438 Handling Controller Actions</a>. 439 </p> 440