TV hardware is substantially different from other Android devices. TVs do not include some of the hardware features found on other Android devices, such as touch screens, cameras, and GPS receivers. TVs are also completely dependent on secondary hardware devices. In order for users to interact with TV apps, they must use a remote control or game pad. When you build an app for TV, you must carefully consider the hardware limitations and requirements of operating on TV hardware.
This lesson shows how to check if your app is running on a TV, and how to handle unsupported hardware features. To learn about various input methods see Manage TV controllers.
Check for a TV device
If you are building an app that operates both on TV devices and other devices, you may need to
check what kind of device your app is running on and adjust the operation of your app. For
instance, if you have an app that can be started through an Intent
, your
application should check the device properties to determine if it should start a TV-oriented
activity or a phone activity.
The recommended way to determine if your app is running on a TV device is to use the PackageManager.hasSystemFeature()
method to check
if the device is running in television mode. The following example code shows you how to check if
your app is running on a TV device:
Kotlin
const val TAG = "DeviceTypeRuntimeCheck" val isTelevision = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK) if (isTelevision) { Log.d(TAG, "Running on a TV Device") } else { Log.d(TAG, "Running on a non-TV Device") }
Java
public static final String TAG = "DeviceTypeRuntimeCheck"; boolean isTelevision = getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK); if (isTelevision) { Log.d(TAG, "Running on a TV Device"); } else { Log.d(TAG, "Running on a non-TV Device"); }
Handle unsupported hardware features
Depending on the design and functionality of your app, you may be able to work around certain hardware features being unavailable. This section discusses what hardware features are typically not available for TV, how to detect missing hardware features, and suggests alternatives to using these features.
Unsupported TV hardware features
TVs have a different purpose from other devices, and so they do not have hardware features that other Android-powered devices often have. For this reason, the Android system does not support the following features for a TV device:
Hardware | Android feature descriptor |
---|---|
Touchscreen | android.hardware.touchscreen |
Touchscreen emulator | android.hardware.faketouch |
Telephony | android.hardware.telephony |
Camera | android.hardware.camera |
Near Field Communications (NFC) | android.hardware.nfc |
GPS | android.hardware.location.gps |
Microphone [1] | android.hardware.microphone |
Sensors | android.hardware.sensor |
Screen in portrait orientation | android.hardware.screen.portrait |
[1] Some TV controllers have a microphone, which is not the same as the microphone hardware feature described here. The controller microphone is fully supported.
See the Features reference for a complete list of features, subfeatures, and their descriptors.
Declaring hardware requirements for TV
Android apps can declare hardware feature requirements in the app manifest to ensure that they do not get installed on devices that do not provide those features. If you are extending an existing app for use on TV, closely review your app's manifest for any hardware requirement declarations that might prevent it from being installed on a TV device.
If your app uses hardware features (such as a touchscreen or camera) that are not available on TV, but can operate without the use of those features, modify your app's manifest to indicate that these features are not required by your app. The following manifest code snippet demonstrates how to declare that your app does not require hardware features which are unavailable on TV devices, even though your app may use these features on non-TV devices:
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/> <uses-feature android:name="android.hardware.faketouch" android:required="false"/> <uses-feature android:name="android.hardware.telephony" android:required="false"/> <uses-feature android:name="android.hardware.camera" android:required="false"/> <uses-feature android:name="android.hardware.nfc" android:required="false"/> <uses-feature android:name="android.hardware.location.gps" android:required="false"/> <uses-feature android:name="android.hardware.microphone" android:required="false"/> <uses-feature android:name="android.hardware.sensor" android:required="false"/> <!-- Some TV devices have an ethernet connection only --> <uses-feature android:name="android.hardware.wifi" android:required="false"/>
Note: Some features have subfeatures like android.hardware.camera.front
,
as described in the
Feature reference. Be sure to mark any subfeatures also used in your app as required="false"
.
All apps intended for use on TV devices must declare that the touch screen feature is not required
as described in Get started with
TV apps. If your app normally uses one or more of the features listed above, change the
android:required
attribute setting to false
for those features in your manifest.
Caution: Declaring a hardware feature as required by setting its
value to true
prevents your app from being installed on TV
devices or appearing in the Android TV home screen launcher.
Once you decide to make hardware features optional for your app, you must check for the availability of those features at runtime and then adjust your app's behavior. The next section discusses how to check for hardware features and suggests some approaches for changing the behavior of your app.
For more information on filtering and declaring features in the manifest, see the
uses-feature
guide.
Declaring permissions that imply hardware features
Some uses-permission
manifest declarations imply hardware features. This behavior means that requesting some
permissions in your app manifest can exclude your app from from being installed and used on TV
devices. The following commonly requested permissions create an implicit hardware feature
requirement:
Permission | Implied hardware feature |
---|---|
RECORD_AUDIO |
android.hardware.microphone |
CAMERA |
android.hardware.camera and android.hardware.camera.autofocus |
ACCESS_COARSE_LOCATION |
|
ACCESS_FINE_LOCATION |
|
ACCESS_WIFI_STATE CHANGE_WIFI_STATE
|
Some TV devices have an ethernet connection only. |
For a complete list of permission requests that imply a hardware feature requirement, see the
uses-feature
guide. If your app requests one of the features listed above, include a
uses-feature
declaration in your manifest for the implied hardware feature that indicates it is not
required (android:required="false"
).
Note: If your app targets Android 5.0 (API level 21) or
higher and uses the ACCESS_COARSE_LOCATION
or
ACCESS_FINE_LOCATION
permission, users can still install your
app on a TV device, even if the TV device doesn't have a network card or a GPS
receiver.
Check for hardware features
The Android framework can tell you if hardware features are not available on the device where
your app is running. Use the hasSystemFeature(String)
method to check for specific features at runtime. This method takes a single string argument that
specifies the feature you want to check.
The following code example demonstrates how to detect the availability of hardware features at runtime:
Kotlin
// Check if the telephony hardware feature is available. if (packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) { Log.d("HardwareFeatureTest", "Device can make phone calls") } // Check if android.hardware.touchscreen feature is available. if (packageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) { Log.d("HardwareFeatureTest", "Device has a touch screen.") }
Java
// Check if the telephony hardware feature is available. if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) { Log.d("HardwareFeatureTest", "Device can make phone calls"); } // Check if android.hardware.touchscreen feature is available. if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)) { Log.d("HardwareFeatureTest", "Device has a touch screen."); }
Touch screen
Since most TVs do not have touch screens, Android does not support touch screen interaction for TV devices. Furthermore, using a touch screen is not consistent with a viewing environment where the user is seated 10 feet away from the display. Make sure that your UI elements and text do not require or imply the use of a touchscreen.
On TV devices, you should design your app to work with this interaction model by supporting navigation using a directional pad (D-pad) on a TV remote control. For more information on properly supporting navigation using TV-friendly controls, see Create TV navigation.
Camera
Although a TV typically does not have a camera, you can still provide a photography-related app on a TV. For example, if you have an app that takes, views, and edits photos, you can disable its picture-taking functionality for TVs and still allow users to view and even edit photos. If you decide to enable your camera-related app to work on a TV, add the following feature declaration your app manifest:
<uses-feature android:name="android.hardware.camera" android:required="false" />
If you enable your app to run without a camera, add code to your app that detects if the camera feature is available and makes adjustments to the operation of your app. The following code example demonstrates how to detect the presence of a camera:
Kotlin
// Check if the camera hardware feature is available. if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) { Log.d("Camera test", "Camera available!") } else { Log.d("Camera test", "No camera available. View and edit features only.") }
Java
// Check if the camera hardware feature is available. if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) { Log.d("Camera test", "Camera available!"); } else { Log.d("Camera test", "No camera available. View and edit features only."); }
GPS
TVs are stationary, indoor devices, and do not have built-in global positioning system (GPS) receivers. If your app uses location information, you can still allow users to search for a location, or use a static location provider such as a zip code configured during the TV device setup.
Kotlin
// Request a static location from the location manager val locationManager = this.getSystemService(Context.LOCATION_SERVICE) as LocationManager val location: Location = locationManager.getLastKnownLocation("static") // Attempt to get postal or zip code from the static location object val geocoder = Geocoder(this) val address: Address? = try { geocoder.getFromLocation(location.latitude, location.longitude, 1)[0] .apply { Log.d(TAG, postalCode) } } catch (e: IOException) { Log.e(TAG, "Geocoder error", e) null }
Java
// Request a static location from the location manager LocationManager locationManager = (LocationManager) this.getSystemService( Context.LOCATION_SERVICE); Location location = locationManager.getLastKnownLocation("static"); // Attempt to get postal or zip code from the static location object Geocoder geocoder = new Geocoder(this); Address address = null; try { address = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1).get(0); Log.d("Zip code", address.getPostalCode()); } catch (IOException e) { Log.e(TAG, "Geocoder error", e); }
Pausing playback during low-power mode
Some TV devices support a low-power mode when the user switches the device off. Instead of shutting down, the device disables the display and keeps Android TV running in the background. Audio output is still enabled in this mode, so your app should stop any currently playing content when the device is in low-power mode.
To avoid playback during low-power mode, override
onStop()
and stop any currently playing content:
Kotlin
override fun onStop() { // App-specific method to stop playback stopPlayback() super.onStop() }
Java
@Override public void onStop() { // App-specific method to stop playback stopPlayback(); super.onStop(); }
When the user switches the power back on, if your app is the active
foreground app, onStart()
is called.
For more information on starting and stopping an activity, see
The activity lifecycle.