Home | History | Annotate | Download | only in start
      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>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 &lt;uses-feature android:name="android.hardware.touchscreen"
    155         android:required="false"/&gt;
    156 &lt;uses-feature android:name="android.hardware.faketouch"
    157         android:required="false"/&gt;
    158 &lt;uses-feature android:name="android.hardware.telephony"
    159         android:required="false"/&gt;
    160 &lt;uses-feature android:name="android.hardware.camera"
    161         android:required="false"/&gt;
    162 &lt;uses-feature android:name="android.hardware.nfc"
    163         android:required="false"/&gt;
    164 &lt;uses-feature android:name="android.hardware.location.gps"
    165         android:required="false"/&gt;
    166 &lt;uses-feature android:name="android.hardware.microphone"
    167         android:required="false"/&gt;
    168 &lt;uses-feature android:name="android.hardware.sensor"
    169         android:required="false"/&gt;
    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>{@code android.hardware.location} <em>and</em> <br>
    231       {@code android.hardware.location.network}</td>
    232   </tr>
    233   <tr>
    234     <td>{@link android.Manifest.permission#ACCESS_FINE_LOCATION}</td>
    235     <td>{@code android.hardware.location} <em>and</em> <br>
    236       {@code android.hardware.location.gps}</td>
    237   </tr>
    238 </table>
    239 
    240 <p>
    241   For a complete list of permission requests that imply a hardware feature requirement, see the
    242   <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#permissions-features">{@code
    243   uses-feature}</a> guide. If your app requests one of the features listed above, include a
    244   <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code uses-feature}</a>
    245   declaration in your manifest for the implied hardware feature that indicates it is not
    246   required ({@code android:required="false"}).
    247 </p>
    248 
    249 
    250 <h3 id="check-features">Checking for hardware features</h2>
    251 
    252 <p>
    253   The Android framework can tell you if hardware features are not available on the device where
    254   your app is running. Use the {@link android.content.pm.PackageManager#hasSystemFeature(String)}
    255   method to check for specific features at runtime. This method takes a single string argument that
    256   specifies the feature you want to check.
    257 </p>
    258 
    259 <p>The following code example demonstrates how to detect the availability of hardware features
    260   at runtime:</p>
    261 
    262 <pre>
    263 // Check if the telephony hardware feature is available.
    264 if (getPackageManager().hasSystemFeature("android.hardware.telephony")) {
    265     Log.d("HardwareFeatureTest", "Device can make phone calls");
    266 }
    267 
    268 // Check if android.hardware.touchscreen feature is available.
    269 if (getPackageManager().hasSystemFeature("android.hardware.touchscreen")) {
    270     Log.d("HardwareFeatureTest", "Device has a touch screen.");
    271 }
    272 </pre>
    273 
    274 
    275 <h4 id="no-touchscreen">Touch screen</h4>
    276 
    277 <p>
    278   Since most TVs do not have touch screens, Android does not support touch screen interaction for
    279   TV devices. Furthermore, using a touch screen is not consistent with a viewing environment where
    280   the user is seated 10 feet away from the display. Make sure that your UI elements and text do not
    281   require or imply the use of a touchscreen.
    282 </p>
    283 
    284 <p>
    285   On TV devices, you should design your app to work with this interaction model by supporting
    286   navigation using a directional pad (D-pad) on a TV remote control. For more information on
    287   properly supporting navigation using TV-friendly controls, see
    288   <a href="{@docRoot}training/tv/start/navigation.html">Creating TV Navigation</a>.
    289 </p>
    290 
    291 
    292 <h4 id="no-camera">Camera</h4>
    293 
    294 <p>
    295   Although a TV typically does not have a camera, you can still provide a photography-related
    296   app on a TV. For example, if you have an app that takes, views, and edits photos, you can
    297   disable its picture-taking functionality for TVs and still allow users to view and even edit
    298   photos. If you decide to enable your camera-related app to work on a TV, add the
    299   following feature declaration your app manifest:
    300 </p>
    301 
    302 <pre>
    303 &lt;uses-feature android:name="android.hardware.camera" android:required="false" /&gt;
    304 </pre>
    305 
    306 <p>
    307   If you enable your app to run without a camera, add code to your app
    308   that detects if the camera feature is available and makes adjustments to the operation of your
    309   app. The following code example demonstrates how to detect the presence of a camera:
    310 </p>
    311 
    312 <pre>
    313 // Check if the camera hardware feature is available.
    314 if (getPackageManager().hasSystemFeature("android.hardware.camera")) {
    315     Log.d("Camera test", "Camera available!");
    316 } else {
    317     Log.d("Camera test", "No camera available. View and edit features only.");
    318 }
    319 </pre>
    320 
    321 
    322 <h4 id="no-gps">GPS</h4>
    323 
    324 <p>
    325   TVs are stationary, indoor devices, and do not have built-in global positioning system (GPS)
    326   receivers. If your app uses location information, you can still allow users to search for
    327   a location, or use a static location provider such as a zip code configured during the TV device
    328   setup.
    329 </p>
    330 
    331 <pre>
    332 // Request a static location from the location manager
    333 LocationManager locationManager = (LocationManager) this.getSystemService(
    334         Context.LOCATION_SERVICE);
    335 Location location = locationManager.getLastKnownLocation("static");
    336 
    337 // Attempt to get postal or zip code from the static location object
    338 Geocoder geocoder = new Geocoder(this);
    339 Address address = null;
    340 try {
    341   address = geocoder.getFromLocation(location.getLatitude(),
    342           location.getLongitude(), 1).get(0);
    343   Log.d("Zip code", address.getPostalCode());
    344 
    345 } catch (IOException e) {
    346   Log.e(TAG, "Geocoder error", e);
    347 }
    348 </pre>
    349 
    350 
    351 <h2 id="controllers">Handling Controllers</h2>
    352 
    353 <p>
    354   TV devices require a secondary hardware device for interacting with apps, in the form of a basic
    355   remote controller or game controller. This means that your app must support D-pad input. It also
    356   means that your app may need to handle controllers going offline and input from more than one
    357   type of controller.
    358 </p>
    359 
    360 
    361 <h3 id="d-pad-minimum">D-pad minimum controls</h3>
    362 
    363 <p>
    364   The default controller for a TV device is a D-pad. In general, your app should be operable from a
    365   remote controller that only has up, down, left, right, select, Back, and Home buttons. If your app
    366   is a game that typically requires a game controller with additional controls, your app should
    367   attempt to allow gameplay with these D-pad controls. In this case, your app should also warn the
    368   user that
    369   a controller is required and allow them to exit your game gracefully using the D-pad controller.
    370   For more information about handling navigation with D-pad controller for TV devices, see
    371   <a href="{@docRoot}training/tv/start/navigation.html">Creating TV Navigation</a>.
    372 </p>
    373 
    374 
    375 <h3 id="controller-disconnects">Handle controller disconnects</h3>
    376 
    377 <p>
    378   Controllers for TV are frequently Bluetooth devices which may attempt to save power by periodically
    379   going into sleep mode and disconnecting from the TV device. This means that an app might be
    380   interrupted or restarted if it is not configured to handle these reconnect events. These events
    381   can happen in any of the following circumstances:
    382 </p>
    383 
    384 <ul>
    385   <li>While watching a video which is several minutes long, a D-Pad or game controller goes into
    386   sleep mode, disconnects from the TV device and then reconnects later on.
    387   </li>
    388   <li>During gameplay, a new player joins the game using a game controller that is not currently
    389   connected.
    390   </li>
    391   <li>During gameplay, a player leaves the game and disconnects a game controller.
    392   </li>
    393 </ul>
    394 
    395 <p>
    396   Any TV app activity that is subject to disconnect and reconnect events must be configured to
    397   handle reconnection events in the app manifest. The following code sample demonstrates how to
    398   enable an activity to handle configuration changes, including a keyboard or navigation device
    399   connecting, disconnecting, or reconnecting:
    400 </p>
    401 
    402 <pre>
    403 &lt;activity
    404   android:name=&quot;com.example.android.TvActivity&quot;
    405   android:label=&quot;&#64;string/app_name&quot;
    406   <strong>android:configChanges="keyboard|keyboardHidden|navigation"</strong>
    407   android:theme=&quot;&#64;style/Theme.Leanback&quot;&gt;
    408 
    409   &lt;intent-filter&gt;
    410     &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
    411     &lt;category android:name="android.intent.category.LEANBACK_LAUNCHER" /&gt;
    412   &lt;/intent-filter&gt;
    413   ...
    414 &lt;/activity&gt;
    415 </pre>
    416 
    417 <p>
    418   This configuration change allows the app to continue running through a reconnection event, rather
    419   than being restarted by the Android framework, which is not a good user experience.
    420 </p>
    421 
    422 
    423 <h3 id="d-pad-variants">Handle D-pad input variations</h3>
    424 
    425 <p>
    426   TV device users may have more than one type of controller that they use with their TV. For
    427   example, a user might have both a basic D-pad controller and a game controller. The key codes
    428   provided by a game controller when it is being used for D-pad functions may vary from the key
    429   codes sent by a physical D-pad.
    430 </p>
    431 
    432 <p>
    433   Your app should handle the variations of D-pad input from a game controller, so the user does not
    434   have to physically switch controllers to operate your app. For more information on handling these
    435   input variations, see <a href="{@docRoot}training/game-controllers/controller-input.html#dpad">
    436   Handling Controller Actions</a>.
    437 </p>
    438