Some of the following will discuss Android TV (“ATV”) specific needs; most of the rest will discuss your application being connected to a TV, such as a set-top box or micro-console (we’ll use “STB” for both). Both topics should complement each other.
A user is likely to be sitting several feet away from the TV. Fonts, buttons, and other UI elements need to take this into account. Most UI elements in your application should be sized larger, especially fonts. Consider this when designing your application’s UI for different resolutions.
There is a technical aspect of TV transmission that can reduce a TV’s usable screen area along the edges; this is called “overscan.” Mobile devices do not have this issue and generally, TVs with a “Game Mode” do not either. However, overscan should be taken into account. A good rule-of-thumb is to make sure you leave a 5% margin around the screen for overscan. Meaning, ensure important application elements are placed inside this margin – health, score, etc.
The slickest way of handling overscan, which is seen in many consoles (and will hopefully be added to Android), is to draw a box around the edge of the “display.” In some cases, because of overscan, some of the entire box will not be visible to the user. The user then is asked, using the controller, to shrink the box’s edges until they see each edge. This box can then be used for placement of UI elements and can allow precise corner placements.
![]() | In the discussions below, a new keycode is mentioned — K In Unity API Specifics, section DPAD and System Buttons, it shows how a |
Consider that many STBs come with just a remote. In the above pages, we discuss a fully featured console-like controller. When considering what controls your application might need, a remote is mostly a subset of the console-like controller discussed. The only addition is KEYCODE_DPAD_CENTER
which should just mimic “A button” functionality. The below chart describes the minimum input you should consider from a remote.
The Remote Control | ||
---|---|---|
Action | Keycode | Uses and Notes |
Push Up | KEYCODE_DPAD_UP AXIS_HAT_Y @ -1.0 | Use for "Up." Use both keycode values for the same action. |
Push Down | KEYCODE_DPAD_DOWN AXIS_HAT_Y @ 1.0 | Use for "Down." Use both keycode values for the same action. |
Push Left | KEYCODE_DPAD_LEFT AXIS_HAT_X @ -1.0 | Use for "Left." Use both keycode values for the same action. |
Push Right | KEYCODE_DPAD_RIGHT AXIS_HAT_X @ 1.0 | Use for "Right." Use both keycode values for the same action. |
Push Center/OK | KEYCODE_DPAD_CENTER KEYCODE_BUTTON_A | Use for "Affirm, OK, Primary Action." Use both keycode values for the same action. |
Back | KEYCODE_BACK | Use for "Back, Negative, Pause." |
Home | KEYCODE_HOME | Used in OS only. |
This controller is very much like a remote (see The Remote above) with an extra button. Sometimes the “OK” button remains in the center of the DPAD. Sometimes the “OK” button is placed with the extra button, thus looking very much like a gamepad from the 1980s. In either case, handling the new button is the same. See the chart below which describes the minimum input you should consider from a mini-controller.
The Mini-Controller | ||
---|---|---|
Action | Keycode | Uses and Notes |
Push Up | KEYCODE_DPAD_UP AXIS_HAT_Y @ -1.0 | Use for "Up." Use both keycode values for the same action. |
Push Down | KEYCODE_DPAD_DOWN AXIS_HAT_Y @ 1.0 | Use for "Down." Use both keycode values for the same action. |
Push Left | KEYCODE_DPAD_LEFT AXIS_HAT_X @ -1.0 | Use for "Left." Use both keycode values for the same action. |
Push Right | KEYCODE_DPAD_RIGHT AXIS_HAT_X @ 1.0 | Use for "Right." Use both keycode values for the same action. |
Push Center/OK or A button | KEYCODE_DPAD_CENTER KEYCODE_BUTTON_A | Use for "Affirm, OK, Primary Action." Use both keycode values for the same action. |
Other Button or B button | KEYCODE_BUTTON_B | Use for "Back, Negative" in menus. Use for other game actions (optional). |
Back | KEYCODE_BACK | Use for "Back, Negative, Pause." |
Home | KEYCODE_HOME | Used in OS only. |
When discussing the console-like controller and filtering events, SOURCE_GAMEPAD
and SOURCE_JOYSTICK
are the sources used to filter. However, with the simplicity of the remote, a new, additional source should be used for filtering — SOURCE_DPAD
.
Notice that the KEYCODES
of the Remote, Mini-Controller, and Console-like controller overlap, so that the user’s expectations are met when moving from one controller to the other. The Console-like controller is the super-set of the controllers with one exception: KEYCODE_DPAD_CENTER
, which should act like KEYCODE_BUTTON_A
in your application, needs to be added. Keep in mind, if your application needs inputs beyond what the Remote offers, the user should be alerted that they need a certain type of controller, and the application should allow a graceful exit using inputs only offered by the minimum input device, the Remote.
As of this writing, Android TV is still in “Developer Preview” mode, so some information may change. Please check the Android TV documentation for additional or changed requirements.
ATV will support a new Leanback UI which is meant for TV scenarios. Only the applications that are designed to work in Leanback mode will be visible; this includes Google Play. To indicate that an application is designed for Leanback mode, developers are required to add some new items to their manifest.
A new intent category has been added so that an application can indicate that a certain activity should be added to the Leanback launcher. An application must declare at least one activity in its manifest that handles a launch intent of type ACTION_MAIN
combined with the new Leanback category. Most applications will support the “normal” launcher along with the Leanback launcher. An example of this:
<activity . . . >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
</activity>
The Leanback launcher allows Leanback-specific banners. A developer indicates this banner in a similar way to indicating their application’s icon, android:icon
. The syntax for the banner is android:logo
, and can be either in the application or activity tag like an icon. No extra text is added on top of or below the banner. Applications should put the banner in the drawable-xhdpi
folder with a size of 320x180
. In Unity, this folder is in the Assets\Plugins\Android\res\drawable-xhdpi
folder. Text should be included in the banner image if needed to disambiguate the application in the launcher.
The launcher uses a flag to differentiate games from all other Leanback applications. Games are displayed in a separate row from regular applications. To indicate whether your application is a game or not, you must use a new metadata declaration in the manifest at the application level.
<application . . .>
<meta-data android:name="isGame" android:value=[ "true" | "false" ]/>
</application>
Above we described only the needs for the new Launcher. Below, we’ll discuss items that currently may be in your application, which may need some thought or change.
The current “Developer Preview” of ATV does not include a browser. This means that certain types of in-game advertising will not work. Ads that ask a user to follow a link or install an application from Google Play will not work. Interstitial and video ads that require no user interaction should be fine.
Making sure your application’s manifest precisely reflects hardware features and permissions needed is critical, or else the application may not be listed in the launcher or Play Store. We’ll go over some common mistakes below.
By default, Google Play assumes that an application requires touchscreen support. ATV, of course, has no touchscreen. To be listed properly, your application needs to declare in its manifest the following element:
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
Further, your application must not define any touch requirements without indicating that it is not required, android:required="false"
. If ATV doesn’t have the particular piece of hardware listed in the manifest, and your application doesn’t indicate that it is not required, the application will not be listed. Be sure to check all features listed in the application’s manifest.
Some features you should not rely on:
Features Not Typical on ATV | |
---|---|
android.hardware.bluetooth | android.hardware.sensor.gyroscope |
android.hardware.camera | android.hardware.sensor.light |
android.hardware.camera.autofocus | android.hardware.sensor.proximity |
android.hardware.camera.flash | android.hardware.telephony |
android.hardware.camera.front | android.hardware.telephony.cdma |
android.hardware.location.gps | android.hardware.telephony.gsm |
android.hardware.microphone | android.hardware.faketouch |
android.hardware.nfc | android.hardware.touchscreen |
android.hardware.sensor.accelerometer | android.hardware.touchscreen.multitouch |
android.hardware.sensor.barometer | android.hardware.touchscreen.multitouch.distinct |
android.hardware.sensor.compass | android.hardware.touchscreen.multitouch.jazzhand |
Some permissions in an application’s manifest can imply certain hardware features are required, even if they are not directly declared. Google Play assumes these implied features are required, unless you specify otherwise in the manifest, by declaring that the feature is explicitly not required, like the touchscreen example above.
Permission | Implied Feature |
---|---|
BLUETOOTH BLUETOOTH_ADMIN | android.hardware.bluetooth |
CAMERA | android.hardware.camera android.hardware.camera.autofocus |
ACCESS_MOCK_LOCATION ACCESS_LOCATION_EXTRA_COMMANDS INSTALL_LOCATION_PROVIDER | android.hardware.location |
ACCESS_COARSE_LOCATION | android.hardware.location.network android.hardware.location |
ACCESS_FINE_LOCATION | android.hardware.location.gps android.hardware.location |
RECORD_AUDIO | android.hardware.microphone |
CALL_PHONE CALL_PRIVILEGED MODIFY_PHONE_STATE PROCESS_OUTGOING_CALLS READ_SMS RECEIVE_SMS RECEIVE_MMS RECEIVE_WAP_PUSH SEND_SMS WRITE_APN_SETTINGS WRITE_SMS | android.hardware.telephony |
ACCESS_WIFI_STATE CHANGE_WIFI_STATE CHANGE_WIFI_MULTICAST_STATE | android.hardware.wifi |
Instead, check for features at runtime by calling PackageManager.hasSystemFeature()
, which can allow your application to dynamically use hardware and/or and remove features as needed.
NVIDIA® GameWorks™ Documentation Rev. 1.0.220830 ©2014-2022. NVIDIA Corporation and affiliates. All Rights Reserved.