1page.title=Handling TV Hardware 2page.tags="unsupported" 3trainingnavtop=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> 52public static final String TAG = "DeviceTypeRuntimeCheck"; 53 54UiModeManager uiModeManager = (UiModeManager) getSystemService(UI_MODE_SERVICE); 55if (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>Near Field Communications (NFC)</td> 104 <td>{@code android.hardware.nfc}</td> 105 </tr> 106 <tr> 107 <td>GPS</td> 108 <td>{@code android.hardware.location.gps}</td> 109 </tr> 110 <tr> 111 <td>Microphone <sup><a href="#cont-mic">[1]</a></sup></td> 112 <td>{@code android.hardware.microphone}</td> 113 </tr> 114 <tr> 115 <td>Sensors</td> 116 <td>{@code android.hardware.sensor}</td> 117 </tr> 118 <tr> 119 <td>Screen in portrait orientation</td> 120 <td>{@code android.hardware.screen.portrait}</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.nfc" 163 android:required="false"/> 164<uses-feature android:name="android.hardware.location.gps" 165 android:required="false"/> 166<uses-feature android:name="android.hardware.microphone" 167 android:required="false"/> 168<uses-feature android:name="android.hardware.sensor" 169 android:required="false"/> 170</pre> 171 172<p class="note"><strong>Note:</strong> Some features have subfeatures like {@code android.hardware.camera.front}, 173 as described in the <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#features-reference"> 174 Feature Reference</a>. Be sure to mark as {@code required="false"} any subfeatures also used in 175 your app.</p> 176 177<p> 178 All apps intended for use on TV devices must declare that the touch screen feature is not required 179 as described in <a href="{@docRoot}training/tv/start/start.html#no-touchscreen">Get Started with 180 TV Apps</a>. If your app normally uses one or more of the features listed above, change the 181 {@code android:required} attribute setting to {@code false} for those features in your manifest. 182</p> 183 184<p class="caution"> 185 <strong>Caution:</strong> Declaring a hardware feature as required by setting its 186 value to {@code true} prevents your app from being installed on TV 187 devices or appearing in the Android TV home screen launcher. 188</p> 189 190<p> 191 Once you decide to make hardware features optional for your app, you must check for the 192 availability of those features at runtime and then adjust your app's behavior. The next section 193 discusses how to check for hardware features and suggests some approaches for changing the 194 behavior of your app. 195</p> 196 197<p> 198 For more information on filtering and declaring features in the manifest, see the 199 <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code uses-feature}</a> 200 guide. 201</p> 202 203 204<h3 id="hardware-permissions">Declaring permissions that imply hardware features</h3> 205 206<p> 207 Some <a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">{@code uses-permission}</a> 208 manifest declarations <em>imply hardware features</em>. This behavior means that requesting some 209 permissions in your app manifest can exclude your app from from being installed and used on TV 210 devices. The following commonly requested permissions create an implicit hardware feature 211 requirement: 212</p> 213 214<table> 215 <tr> 216 <th>Permission</th> 217 <th>Implied hardware feature</th> 218 </tr> 219 <tr> 220 <td>{@link android.Manifest.permission#RECORD_AUDIO}</td> 221 <td>{@code android.hardware.microphone}</td> 222 </tr> 223 <tr> 224 <td>{@link android.Manifest.permission#CAMERA}</td> 225 <td>{@code android.hardware.camera} <em>and</em> <br> 226 {@code android.hardware.camera.autofocus}</td> 227 </tr> 228 <tr> 229 <td>{@link android.Manifest.permission#ACCESS_COARSE_LOCATION}</td> 230 <td> 231 <p>{@code android.hardware.location}</p> 232 <p>{@code android.hardware.location.network} (Target API level 20 or lower 233 only.)</p> 234 </td> 235 </tr> 236 <tr> 237 <td>{@link android.Manifest.permission#ACCESS_FINE_LOCATION}</td> 238 <td> 239 <p>{@code android.hardware.location}</p> 240 <p>{@code android.hardware.location.gps} (Target API level 20 or lower 241 only.)</p> 242 </td> 243 </tr> 244</table> 245 246<p> 247 For a complete list of permission requests that imply a hardware feature requirement, see the 248 <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#permissions-features">{@code 249 uses-feature}</a> guide. If your app requests one of the features listed above, include a 250 <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code uses-feature}</a> 251 declaration in your manifest for the implied hardware feature that indicates it is not 252 required ({@code android:required="false"}). 253</p> 254 255<p class="note"> 256 <strong>Note:</strong> If your app targets Android 5.0 (API level 21) or 257 higher and uses the <code>ACCESS_COARSE_LOCATION</code> or 258 <code>ACCESS_FINE_LOCATION</code> permission, users can still install your 259 app on a TV device, even if the TV device doesn't have a network card or a GPS 260 receiver. 261</p> 262 263<h3 id="check-features">Checking for hardware features</h2> 264 265<p> 266 The Android framework can tell you if hardware features are not available on the device where 267 your app is running. Use the {@link android.content.pm.PackageManager#hasSystemFeature(String)} 268 method to check for specific features at runtime. This method takes a single string argument that 269 specifies the feature you want to check. 270</p> 271 272<p>The following code example demonstrates how to detect the availability of hardware features 273 at runtime:</p> 274 275<pre> 276// Check if the telephony hardware feature is available. 277if (getPackageManager().hasSystemFeature("android.hardware.telephony")) { 278 Log.d("HardwareFeatureTest", "Device can make phone calls"); 279} 280 281// Check if android.hardware.touchscreen feature is available. 282if (getPackageManager().hasSystemFeature("android.hardware.touchscreen")) { 283 Log.d("HardwareFeatureTest", "Device has a touch screen."); 284} 285</pre> 286 287 288<h4 id="no-touchscreen">Touch screen</h4> 289 290<p> 291 Since most TVs do not have touch screens, Android does not support touch screen interaction for 292 TV devices. Furthermore, using a touch screen is not consistent with a viewing environment where 293 the user is seated 10 feet away from the display. Make sure that your UI elements and text do not 294 require or imply the use of a touchscreen. 295</p> 296 297<p> 298 On TV devices, you should design your app to work with this interaction model by supporting 299 navigation using a directional pad (D-pad) on a TV remote control. For more information on 300 properly supporting navigation using TV-friendly controls, see 301 <a href="{@docRoot}training/tv/start/navigation.html">Creating TV Navigation</a>. 302</p> 303 304 305<h4 id="no-camera">Camera</h4> 306 307<p> 308 Although a TV typically does not have a camera, you can still provide a photography-related 309 app on a TV. For example, if you have an app that takes, views, and edits photos, you can 310 disable its picture-taking functionality for TVs and still allow users to view and even edit 311 photos. If you decide to enable your camera-related app to work on a TV, add the 312 following feature declaration your app manifest: 313</p> 314 315<pre> 316<uses-feature android:name="android.hardware.camera" android:required="false" /> 317</pre> 318 319<p> 320 If you enable your app to run without a camera, add code to your app 321 that detects if the camera feature is available and makes adjustments to the operation of your 322 app. The following code example demonstrates how to detect the presence of a camera: 323</p> 324 325<pre> 326// Check if the camera hardware feature is available. 327if (getPackageManager().hasSystemFeature("android.hardware.camera")) { 328 Log.d("Camera test", "Camera available!"); 329} else { 330 Log.d("Camera test", "No camera available. View and edit features only."); 331} 332</pre> 333 334 335<h4 id="no-gps">GPS</h4> 336 337<p> 338 TVs are stationary, indoor devices, and do not have built-in global positioning system (GPS) 339 receivers. If your app uses location information, you can still allow users to search for 340 a location, or use a static location provider such as a zip code configured during the TV device 341 setup. 342</p> 343 344<pre> 345// Request a static location from the location manager 346LocationManager locationManager = (LocationManager) this.getSystemService( 347 Context.LOCATION_SERVICE); 348Location location = locationManager.getLastKnownLocation("static"); 349 350// Attempt to get postal or zip code from the static location object 351Geocoder geocoder = new Geocoder(this); 352Address address = null; 353try { 354 address = geocoder.getFromLocation(location.getLatitude(), 355 location.getLongitude(), 1).get(0); 356 Log.d("Zip code", address.getPostalCode()); 357 358} catch (IOException e) { 359 Log.e(TAG, "Geocoder error", e); 360} 361</pre> 362 363 364<h2 id="controllers">Handling Controllers</h2> 365 366<p> 367 TV devices require a secondary hardware device for interacting with apps, in the form of a basic 368 remote controller or game controller. This means that your app must support D-pad input. It also 369 means that your app may need to handle controllers going offline and input from more than one 370 type of controller. 371</p> 372 373 374<h3 id="d-pad-minimum">D-pad minimum controls</h3> 375 376<p> 377 The default controller for a TV device is a D-pad. In general, your app should be operable from a 378 remote controller that only has up, down, left, right, select, Back, and Home buttons. If your app 379 is a game that typically requires a game controller with additional controls, your app should 380 attempt to allow gameplay with these D-pad controls. In this case, your app should also warn the 381 user that 382 a controller is required and allow them to exit your game gracefully using the D-pad controller. 383 For more information about handling navigation with D-pad controller for TV devices, see 384 <a href="{@docRoot}training/tv/start/navigation.html">Creating TV Navigation</a>. 385</p> 386 387 388<h3 id="controller-disconnects">Handle controller disconnects</h3> 389 390<p> 391 Controllers for TV are frequently Bluetooth devices which may attempt to save power by periodically 392 going into sleep mode and disconnecting from the TV device. This means that an app might be 393 interrupted or restarted if it is not configured to handle these reconnect events. These events 394 can happen in any of the following circumstances: 395</p> 396 397<ul> 398 <li>While watching a video which is several minutes long, a D-Pad or game controller goes into 399 sleep mode, disconnects from the TV device and then reconnects later on. 400 </li> 401 <li>During gameplay, a new player joins the game using a game controller that is not currently 402 connected. 403 </li> 404 <li>During gameplay, a player leaves the game and disconnects a game controller. 405 </li> 406</ul> 407 408<p> 409 Any TV app activity that is subject to disconnect and reconnect events must be configured to 410 handle reconnection events in the app manifest. The following code sample demonstrates how to 411 enable an activity to handle configuration changes, including a keyboard or navigation device 412 connecting, disconnecting, or reconnecting: 413</p> 414 415<pre> 416<activity 417 android:name="com.example.android.TvActivity" 418 android:label="@string/app_name" 419 <strong>android:configChanges="keyboard|keyboardHidden|navigation"</strong> 420 android:theme="@style/Theme.Leanback"> 421 422 <intent-filter> 423 <action android:name="android.intent.action.MAIN" /> 424 <category android:name="android.intent.category.LEANBACK_LAUNCHER" /> 425 </intent-filter> 426 ... 427</activity> 428</pre> 429 430<p> 431 This configuration change allows the app to continue running through a reconnection event, rather 432 than being restarted by the Android framework, which is not a good user experience. 433</p> 434 435 436<h3 id="d-pad-variants">Handle D-pad input variations</h3> 437 438<p> 439 TV device users may have more than one type of controller that they use with their TV. For 440 example, a user might have both a basic D-pad controller and a game controller. The key codes 441 provided by a game controller when it is being used for D-pad functions may vary from the key 442 codes sent by a physical D-pad. 443</p> 444 445<p> 446 Your app should handle the variations of D-pad input from a game controller, so the user does not 447 have to physically switch controllers to operate your app. For more information on handling these 448 input variations, see <a href="{@docRoot}training/game-controllers/controller-input.html#dpad"> 449 Handling Controller Actions</a>. 450</p> 451