开发者控制台
感谢您的访问。此页面目前仅提供英语版本。我们正在开发中文版本。谢谢您的理解。

Step 3: Insert Your First Channel

Now it’s time to insert your first channel. Besides this diagram, review the diagram for TIF architecture under Android Development Basics.

Flow for inserting your channel

The TV Input inserts channel and program metadata into the TV Input Framework (TIF) database. This data will be used to display your service’s live content in the Fire TV Live sections. TV Input channel and program metadata must be up to date and match the data inside the app. Steps 3 and 4 demonstrate how to insert this data and keep it up to date.

Add the AndroidManifest to Request Permission

<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
<uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />

These permissions must be added to AndroidManifest.xml before your app will be able to interact with the TIF database.

Insert Channel Metadata into Android’s TV Database

Here is an example of how to insert a bare-bones channel into Android’s TV Database. Add the following code to your SetupActivity class: There are two ways you can insert a bare-bones channel into Android's TV Database. You can insert the channel to a class or an object:

SetupActivity class
import android.content.ContentValues;
import android.media.tv.TvContract;
import android.util.Log;
import android.net.Uri;

private long insertChannel() {
    ContentValues values = new contentValues();
    values.put(TvContract.Channels.COLUMN_INPUT_ID, "com.example.android.sampletvinput/.RichTvInputService");
    values.put(TvContract.Channels.COLUMN_DISPLAY_NAME, "My Test Channel");
    values.put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, "3");

    Uri uri = getApplicationContext().getContentResolver().insert(TvContract.Channels.CONTENT_URI, values);
    Log.i("SetupActivity", "Channel Inserted! Uri: " + uri);
    long channelId = Long.parseLong(uri.getLastPathSegment());

    return channelId;
}
Channel object provided in the AndroidX library
import androidx.tvprovider.media.tv.Channel;
import android.media.tv.TvContract;
import android.util.Log;
import android.net.Uri;

private long insertChannel() {
    Channel testChannel = new Channel.Builder()
        .setDisplayName("My Test Channel")
        .setDisplayNumber("3")
        .setInputId("com.example.android.sampletvinput/.RichTvInputService")
        .build();

    Uri uri = getApplicationContext().getContentResolver().insert(TvContract.Channels.CONTENT_URI, testChannel.toContentValues());
    Log.i("SetupActivity", "Channel Inserted! Uri: " + uri);
    long channelId = Long.parseLong(uri.getLastPathSegment());

    return channelId;
}

Next, invoke the method in the onCreate() method in your SetupActivity (replace the existing code)

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.rich_setup);

    insertChannel();
}
Activity Required? Input Notes
COLUMN_INPUT_ID Yes The full class path to the TvInputService Example: TvInputService is in the main app package, then the full class path is <app package>/<relative path to your TvInputService>. If TvInputService is in a separate package, then the inputId should be <app package>/<full separate package + path to TvInputService>.
TvContract.Channels.CONTENT_URI Yes This is the URI pointing to the channel table in Android’s TV Database.
ContentResolver.bulkInsert() or ContentResolver.applyBatch() Yes, in production code One of these ensures all channel insertions happen with one database operation.

Insert GracenoteId

If you are not using Gracenote, skip this section.

Gracenote is a TV catalog provider that integrates with Fire TV to provide channel and program metadata from the cloud. If your content is integrated with Gracenote, you may provide unique IDs which the Fire TV will use to gather this metadata. If you are interested in integrating with Gracenote, reach out to your Amazon contact for more information.

Here is an example of inserting the unique channel Gracenote ID into a JSON object using Amazon's contract keys to indicate both the type and ID. You can place this inside the insert channels function in SetupActivity.java.

/**
 * Type of external id, list of types need to be defined as contant in the wiki (Contract of list below)
 * Null or invalid data will result in failed service match of metadata
 */
private final static String AMZ_KEY_EXTERNAL_ID_TYPE = "externalIdType";

/**
 * The ID for Gracenote input type
 */
private final static String EXTERNAL_ID_TYPE_GRACENOTE_ONTV = "gracenote_ontv"; // gracenote ontv id
private final static String EXTERNAL_ID_TYPE_GRACENOTE_GVD = "gracenote_gvd"; // gracenote gvd id

/**
 * Value of external id, used for matching service meta-data.
 * Null or invalid data will result in failed service match of meta data
 */
private final static String AMZ_KEY_EXTERNAL_ID_VALUE = "externalIdValue";
...

try {
    String jsonString = new JSONObject()
        .put(AMZ_KEY_EXTERNAL_ID_TYPE, EXTERNAL_ID_TYPE_GRACENOTE_ONTV)
        .put(AMZ_KEY_EXTERNAL_ID_VALUE, < gracenote Id > )
        .put(AMZ_KEY_PLAYBACK_DEEP_LINK_URI, playbackDeepLinkIntent.toUri(Intent.URI_INTENT_SCHEME))
        .toString();

    values.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA, jsonString.getBytes());
} catch (JSONException e) {
    Log.e(TAG, "Error when adding data to blob " + e);
}
Activity Required? Notes
externalIdType and externalIdValue Yes These field names are part of the contract between developers and Amazon to provide Gracenote information to Fire TV. Do not change these strings.
TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA Yes This is part of the contract between developers and Amazon to provide deeplink and Gracenote information to Fire TV.
  • If you have another type of Gracenote ID, check to see which kind. If you are uncertain about this, reach out to your Amazon contact.
  • If you plan to use Gracenote, but don't have your Gracenote ID yet, you may temporarily use the following for development purposes. In the US/UK/DE, you can use these sample IDs: 10171 (Disney Channel), 10240 (HBO), and 12131 (Cartoon Network), with the gracenote_ontv externalIdType. For all other marketplaces, you can use sample ID GN9BBXQSECYVNGW (HBO) with the gracenote_gvd externalIdType.

If you've chosen to use deeplink, insert the deeplink into a JSON object using Amazon's contract key string playbackDeepLinkUri.

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

...

Intent playbackDeepLinkIntent = new Intent();
...
// construct the channel contentValues
ContentValues values = new contentValues();
values.put(Channels.COLUMN_INPUT_ID, inputId);
values.put(Channels.COLUMN_DISPLAY_NAME, channel.name);
...
// construct the deeplink Intent
playbackDeepLinkIntent = //deeplink intent for provider's channel
    ...
    try {
        String jsonString = new JSONObject()
            .put(AMZ_KEY_PLAYBACK_DEEP_LINK_URI, playbackDeepLinkIntent.toUri(Intent.URI_INTENT_SCHEME))
            .toString();

        // add jsonString into the channel contentValues
        values.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA, jsonString.getBytes());
    } catch (JSONException e) {
        Log.i(TAG, "Error when adding data to blob " + e);
    }

Uri uri = context.getContentResolver().insert(TvContract.Channels.CONTENT_URI, values);
Activity Required? Notes
playbackDeepLinkUri Yes This is part of the contract between developers and Amazon to provide a channel deeplink to Fire TV. Do not change this string.
TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA Yes This is part of the contract between developers and Amazon to provide deeplink and Gracenote information to Fire TV.

Checkpoint - Display One Channel On Fire TV’s UI

  1. Build and install your APK onto Fire TV.
  2. Navigate to Settings > Live TV > Sync Sources and select the source.
  3. Navigate to Home > On Now row. The inserted channel should appear as one of the cards (boxes with content, sometimes called a tile). For non-Gracenote, you will see a gray tile with a channel name. If there are a number of channels on your device from other sources, yours may not show (there is a limit).
  4. Navigate to Live TV > Channel Guide, open the Options menu (3 lines) > Filter Channels > your input name. The inserted channel should appear on the screen as a row.
  5. Navigate to Settings > Live TV > Manage Channels. Your input name (from the job service XML file) should appear under the list and have the inserted channel assigned to it.
  6. (If using deeplink) Click the channel card in the On Now row. The app should launch and display the expected channel.
  7. (if Gracenote integrated) The channel will show the full program metadata in the On Now row and in the Channel Guide.

Troubleshooting

The channel is not showing up in the On Now row or Channel Guide

  • Refer to the Checkpoint to verify it’s added to the allow list.
  • Verify that the inputId of that channel equals the full class path to TvInputService.
  • Verify that the Debug APKs and the production APKs have the same package names.
  • Verify that the channel is being correctly inserted into TIF.
    • Create a hard-code query for channel information right after the insert to ensure the channel is in the database.
  • Verify that Amazon picks up the channel correctly.
    • Before inserting the channel, view adb logs:

      For Mac / Linux adb logcat | grep StationSync

      For Windows adb logcat | findstr StationSync

    • After you insert the channel, you should be able to see logs similar to what you find below. “Added” means Amazon is recognizing a new channel in Android’s TV Database.

08-07 15:24:57.101 11882 11941 I StationSync: Started full channel sync
08-07 15:24:57.188 11882 11941 I StationSync: Finished full channel sync, found: 15, added: 1, removed: 0, updated: 0

The channel is shown as a blank tile in On Now, with no image (only a channel name)

  • This is expected behavior if a channel is not Gracenote integrated. If it is Gracenote integrated, see below.

The channel has a Gracenote ID, but no metadata shows up in On Now or the Channel Guide

  • Make sure you know if your feed is for onTV or GVD and define it correctly in TvContractUtils. Amazon catalog supports onTV for certain marketplaces. If there is a mismatch between what Amazon supports and what type of Gracenote ID you have, please reach out to your Amazon contact. They will likely work with Gracenote to correct the issue, or switch to TIF.
  • Double check the Gracenote ID value. onTV utilizes numerical values only, while GVD is alphanumeric.

Next Steps

If you are not using Gracenote, go to the next step: Step 4: Insert Programs.

If you are using Gracenote, skip Step 4 and go to the following: Step 5: Playback in Fire TV UI.


Last updated: May 21, 2021