• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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&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>
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&lt;uses-feature android:name="android.hardware.camera" android:required="false" /&gt;
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&lt;activity
417  android:name=&quot;com.example.android.TvActivity&quot;
418  android:label=&quot;&#64;string/app_name&quot;
419  <strong>android:configChanges="keyboard|keyboardHidden|navigation"</strong>
420  android:theme=&quot;&#64;style/Theme.Leanback&quot;&gt;
421
422  &lt;intent-filter&gt;
423    &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
424    &lt;category android:name="android.intent.category.LEANBACK_LAUNCHER" /&gt;
425  &lt;/intent-filter&gt;
426  ...
427&lt;/activity&gt;
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