No results found

Try a different or more specific query
Developer Console

Live TV Resources

The following best practices, code samples, and other references will help you better understand the specifics of live integration during the implementation phase.

Add Package to Allow List

An allow list determines which applications are capable of surfacing their channels in the Fire TV browse and search.


Linear TV integrations for Fire TV are currently only available for selected partners. We expect to be able to enable this feature for all developers in the near future.

Best Practices

The following product and implementation guidelines will help provide your customers with the best live TV experience on Fire TV:

  • Provide a friction-free sign-up to encourage trial where applicable. Examples include simplifying registration forms on the application or utilizing a phone number to sign up.
  • Use a transparent, monochrome logo for each TvContract.Channels.Logo in your channel lineup.
  • Optimize the deep-link flow to begin full-screen playback in less than 2.5 seconds.
  • Use bulk actions anytime you are manipulating more than one channel.
  • Leverage Gracenote channel IDs where applicable to simplify integration.
  • Focus on metadata loading performance optimizations over having full schedule availability or preferred image sizes.
  • Use JobScheduler or WorkManager to periodically check and ensure entitlements are always accurate. This will ensure your channels in browse and search are in sync with the entitled channels at all times, even if your application is not in the foreground.
  • With the exception of a custom channel order, update your entitled channel list in place is preferred to removing and re-adding all channels if the entitled channel list has changed slightly.
  • Provide a displayable channel name for COLUMN_DISPLAY_NAME column since this may be used as a fallback in the UI. Fire TV displays up to 16 alphanumeric or 8-10 full-width characters.
  • Before performing any modifications, query the TIF database each time to determine which channels are already in the database.
  • Before inserting a channel, make sure it is not already present. If the channel is already present, check the metadata to see if it is up to date. Only if metadata needs to be updated should a database update operation be executed.
  • The database cursor should be checked to be null. If the cursor is null, send a delete request for all channels with your input ID, and then reinsert channels.

Code Samples

This section contains code samples related to live TV integrations.

The following code from shows how to include a Gracenote ID and deeplink into the TV database.

 * Variable to store the type of external ID, which is used for the matching service metadata. Valid types are
 * defined below as constants with prefix "EXTERNAL_ID_TYPE_"
 * Null or invalid data will result in failed service
 * match of metadata
private final static String EXTERNAL_ID_TYPE = "externalIdType";

 * Variable to store the value of external ID, which is used for the matching service metadata.
 * Null or invalid data will result in failed service match of metadata
private final static String EXTERNAL_ID_VALUE = "externalIdValue";

 * Uri for deep link of playback into external player.
 * Null or invalid data will result in default as integrated with Fire TV Native Player
private final static String PLAYBACK_DEEP_LINK_URI = "playbackDeepLinkUri";

// The Id for Gracenote input type
private final static String GRACENOTE_ID = "gracenote_ontv"; // gracenote ontv id
private final static String GRACENOTE_GVD = "gracenote_gvd"; // gracenote gvd id

// Contract for playback deep link uri
// Use Intent.URI_INTENT_SCHEME to create uri from intent and to covert back to original intent
Intent playbackDeepLinkIntent = new Intent(); // Created by your app
String playbackDeepLinkUri = playbackDeepLinkIntent.toUri(Intent.URI_INTENT_SCHEME);

// Construct BLOB
ContentValues values = new ContentValues();  // store all the channel data
ContentResolver resolver = context.getContentResolver();
values.put(TvContract.Channels.COLUMN_DISPLAY_NAME, "#Actual display name#");
values.put(TvContract.Channels.COLUMN_INPUT_ID, "#Actual input id#");
try {
    String jsonString = new JSONObject()
                  .put(EXTERNAL_ID_TYPE, "#Actual Id Type#") // replace with GRACENOTE_XXX
                  .put(EXTERNAL_ID_VALUE, "#Actual Id Value#") // replace with gracenote ID value associated with channel
                  .put(PLAYBACK_DEEP_LINK_URI, playbackDeepLinkUri).toString();

    values.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA, jsonString.getBytes());
} catch (JSONException e) {
    Log.e(TAG, "Error when adding data to blob " + e);

Uri uri = resolver.insert(TvContract.Channels.CONTENT_URI, values);

Honoring Parental Controls

The following code demonstrates how to listen to parental controls for live preview or native full screen playback.

private TvContentRating mBlockedRating = null;

    public boolean onTune(final Uri channelUri) {
        if (mTvInputManager.isParentalControlsEnabled()) {
            // ensure playback is not audible or visible on the Surface
            mBlockedRating = <content_rating>;
            // 1. Triggers PIN prompt to user when in fullscreen playback
            // 2. Ensures the program image does not flip to the playback Surface
            //    when browsing the On Now row.
        } else {
            // playback should start

    public void onUnblockContent(final TvContentRating unblockedRating) {
        // the user successfully entered their PIN to unblock content for the
        // provided rating
        if (unblockedRating.unblockContent(mBlockedRating)) {
            // playback should start

Providing an Application Banner

In order to show your application banner in Live TV settings, you will need to provide an application banner through the package manager.

// in AndroidManifest.xml
    tools:replace="android:allowBackup, allow:label, android:theme" >


To test the banner, refer to this code snippet:

Drawable appDrawable = null;
try {
    String packageName = "****"; // replace **** with real package name
    PackageManager packageManager = getContext().getPackageManager();
    appDrawable = packageManager.getApplicationBanner(packageName);
} catch (PackageManager.NameNotFoundException e) {
    Log.i(TAG, "Can't find application banner for package : " + packageName);

Sample Live TV App

A sample app with live TV integration is available on GitHub at This sample TV app is based on the Google sample TV app. You can use this sample app as a reference for the live TV integration on Fire TV.

Locale Support for Live Apps

The sample app is supported only in the following locales: US, CA, UK, DE, JP, ES, and IN. Other marketplace support is coming soon.

To load the sample app:

  1. Go to, click Clone or download, and then click Download ZIP. Unzip the download.

    The app shows sample code for integrating live TV. To see the result, use ADB to sideload the app-debug.apk file onto your Fire TV, as described in the following steps.

  2. Connect to Fire TV through ADB.

    If you've already turned on debugging and have adb installed, just get your Fire TV's IP address from Settings > Device & Software (or My Fire TV) > About > Network and run the following, customizing the IP address for your own Fire TV:

    adb connect 123.456.7.89:5555

    Replace 123.456.7.89 with your Fire TV's IP address. (If you have trouble connecting and you're on your corporate VPN, try disconnecting from VPN, since your computer needs to be on the same wifi network as your Fire TV.)

  3. Install the built APK in the sample app:

    adb install -r AndroidTvSampleInput/app/build/outputs/apk/app-debug.apk

    The response is as follows:

    Performing Streamed Install

    Note that this sample app does not launch as a standalone app in the traditional sense. Instead, it incorporates code for live TV channels available from the Fire TV device.

  4. On your Fire TV device, go to Settings > Applications > Manage Installed Applications. Select Sample TV Inputs. Then click Launch application.

    Sample TV inputs
    Sample TV inputs

    This will take you to the Amazon developer portal.

    Amazon Fire TV site
    Amazon Fire TV site
  5. On your Fire TV remote, click the Home button to back out of this screen. Then go to Settings > Live TV > Sync Sources > Amazon Sample TV Input.

    This will load the sample channels.

    Syncing sources
    Syncing sources
  6. After the sync finishes, click the Home button. Channels should now be visible in the "On Now" row and Guide.

    Here's the "On Now" row:

    Fire TV 'On Now' row
    Fire TV 'On Now' row

    Here's the Channel Guide.

    Fire TV Channel Guide
    Fire TV Channel Guide

    To navigate to the Channel Guide on Fire TV, go to your Home screen, scroll down to the "On Now" row, press the menu button on your remote, and then click Channel Guide. You can also click the mic button on your remote and say, "Channel Guide."

Customized Log Debugging

How to Find All Your Existing Channels

Here’s an example of how to query Android’s TV Database for all existing channels.

private static String[] CHANNEL_TABLE_PROJECTIONS = new String[] {

public List < Channel > getChannels(ContentResolver resolver) {
    Log.d(Utils.DEBUG_TAG, "Start testing query channel table for preview channels...");
    Cursor cursor = null;
    List < Channel > channels = new ArrayList < > ();
    try {
        cursor = resolver.query(TvContractCompat.Channels.CONTENT_URI, CHANNEL_TABLE_PROJECTIONS, null, null, null);
        if (cursor == null || cursor.getCount() == 0) {
            Log.d(TAG, "No channel inserted \n");
            return null;
        while (cursor.moveToNext()) {
            Channel channel = Channel.fromCursor(cursor);
            Log.d(TAG, "Found channel " + channel);
    } catch (Exception e) {
        Log.d(TAG, "Unable to get the channels " + e);
        return null;
    } finally {
        if (cursor != null) {

    return channels;

How to Find All Your Programs in a Channel

Here is how you query for existing programs.

Code Sample: Example of querying program metadata belonging to a specific channel:

public static List < Program > getPrograms(ContentResolver resolver, Uri channelUri) {
    if (channelUri == null) {
        return null;
    Uri uri = TvContract.buildProgramsUriForChannel(channelUri);
    List < Program > programs = new ArrayList < > ();
    // TvProvider returns programs in chronological order by default.
    Cursor cursor = null;
    try {
        cursor = resolver.query(uri, Program.PROJECTION, null, null, null);
        if (cursor == null || cursor.getCount() == 0) {
            return programs;
        while (cursor.moveToNext()) {
    } catch (Exception e) {
        Log.w(TAG, "Unable to get programs for " + channelUri, e);
    } finally {
        if (cursor != null) {
    return programs;

Last updated: May 10, 2021