Developer Console

Events Integration on Fire TV

Fire TV events are standalone events that either take place as you watch them (live events) or are rebroadcast later. Sports events and live concerts are good examples of possible live events.

This document will help you engage your customers with Fire TV events, and how to play or replay this content in the Fire TV UI.

For more on Linear TV, Video on Demand, and Live Events, see Important Definitions.

Features on Fire TV

After completing the Fire TV events integration, any customers who install and sign in to your app will see a dedicated partner-branded row of video content which can be updated in real-time. When the customer changes the focus to any event on the row, rich metadata and playback of the event begins in the upper-right corner.

Focus state on currently airing live event.
Focus state on currently airing live event.
Focus state on short form clip content.
Focus state on short form clip content.

When a user selects an event card, full-screen playback launches in your app:

Fullscreen playback in your app.
Fullscreen playback in your app.

Content Supported

Here is the video content we support:

  1. Instantaneous Live Events - Live feeds, such as a Twitch feed.
  2. Scheduled Live and Future Events - Like a pay-per-view event, or the Olympic Games.
  3. Linear Channels - A show that is broadcast according to a schedule, like traditional cable TV.
  4. Catch-up and Rebroadcasts (VOD) - Available to watch whenever you want.
  5. Highlights, Condensed Games, Interviews (Short form VOD) - Similar to #4, but a shorter venue, such as game highlights.

Certification Checklist

Amazon uses the following checklist to certify the events integration in your app. Your application's implementation directly affects the expected behaviors listed below. Any exceptions to the certification will be handled on a case-by-case basis.

Entitlement State Changes

  • Entitlement should result in one click to full-screen playback. In most cases, customer-entitled events will populate in the Fire TV UI after a customer installs, opens, and signs into your application.
  • Content must be removed from the Fire TV UI when the customer loses entitlement. Examples include membership expiration, logging out of your app, or uninstalling your app.

Browse and Playback Experience

  • Event metadata, including the event title, description, start/end time (if applicable), and content-forward image, are mandatory to ensure a smooth user experience. This metadata must be pushed onto the device as part of the database information.
  • When customers focus on live content, a video feed (live preview) replaces the background image.
  • When customers focus on the event tile and press the context menu button, they can select "Watch with <your app name>" or "Launch." "Watch with" will deeplink to full-screen playback within your app, while "Launch" will deeplink to the main app UI of your app. Deeplinks must be provided by your app to push your video information to the device.
  • A PIN prompt will show prior to playback if parental controls are enabled for apps. Live channel previews must be disabled if parental controls is enabled.
  • Accessing an event via the select button or the "Watch with" context menu item will deeplink to full-screen playback within your app to play that content directly if the event is currently airing. If the event selected is airing in the future or if it's a replay of a live event, the ingress will point to the event detail page or to full-screen playback in your app. Pressing the back button will return to the Fire TV UI in one or two button presses, but no more.

Development, Staging, and Deployment

  • Amazon must have the ability to add specific accounts to an allow list for review and certification of the events experience before it can go into production.
  • The events feature must be enabled only in marketplaces that have been agreed upon with your Amazon contact. Subsequent launches in new marketplaces will require a new certification process.

Recommendation Channels on Fire TV

Events Integration on Fire TV is based on the Android’s recommendation channels on the home screen. This was originally introduced in Android 8.0 (API level 26), but Fire OS has been updated to support this API across all Fire TV devices (even those devices prior to API level 26).

Allow Listing Your App Package

To display content in your live event row for development, you need to first be added to an allow list. Share this information with your Amazon counterpart:

  1. Your application's package name.
  2. The display name you want for your row (choose an appropriate length to ensure it looks good across different UIs).
  3. A list of testing Device Serial Numbers (DSNs). DSNs enable your device to see content in the Electronic Program Guide (EPG), while the Customer ID (CID) enables you to see content in the Live Tab. This will ensure you are able to validate the features outlined above on your device prior to launching.

Provider Attribution

Provide your Amazon counterpart with a single monochrome logo that represents your application's branding. This will be overlaid on your content’s preview image that is displayed when the user browses your live event row. This image file must be 34px high with a maximum width covering 25% of the overlaying image in a horizontal orientation.

Feature Compatibility

Your application should have a unified implementation across Fire TV devices. Amazon has back-ported this feature, which was initially introduced with Android O (API level 26), to earlier versions of Fire TV devices (Fire OS 5 and 6). To ensure your application runs correctly, check for feature compatibility in places where you are interacting with the database. (Refer to Check Feature Compatibility in the Code Samples sections below.)

Recommendation Channel

Your application should be updated to push one and only one recommendation channel (which contains PREVIEW as the type, and an empty inputId field) into the local channels database. Your application must create one (and only one) recommendation channel, define type as PREVIEW, and you must set the APP_LINK_INTENT_URI to point to your main app activity. Provide a displayName that closely matches your application name, and do not set inputId. If you insert more than one recommendation channel, additional recommendation channels and their related preview programs in the database will not be recognized as valid content for this integration.

Event Entitlements and Ordering

After you create the channel, update your app to push entitled content into the local database on Fire TV devices. Content can be added, updated, or removed while your application is running in the background. The existence of content in this database implies that customers are entitled to view the content. The database will be referenced as the authority for all content displayed to customers. Content can be added or removed from this database at any time, and the changes will be reflected in the UI within 5 minutes.

The sort order of the events in your application are based on program weight, with fallback to program insert order. Fire TV recommends that you place your most topical content to the front, emphasizing currently airing programs at the front of the row for highest visibility.

Programming Metadata Attributes

Fire TV will manage the UI refresh, but your application will be responsible for all content. Your application will insert programs of TYPE_EVENT, TYPE_CHANNEL, or TYPE_CLIP into the Android database. While we recommend that you fill TvContractCompat.PreviewPrograms to the fullest extent possible, the following table provides the minimum and recommended attributes to ensure the best content-forward experience on our platform. Most of the metadata below will be displayed as part of the "mini-details," which is the section at the top-left hand corner when content is under focus.

Program metadata in display.
Program metadata in display.

The following table lists possible metadata. The callouts in the above image correspond to the "Reference" column in the table below:

Available TIF Field & Preview Program Column Purpose Reference Required?
channel_id
COLUMN_CHANNEL_ID
Maps live event to preview channel. Yes
type
COLUMN_TYPE
Must be set as PreviewPrograms.TYPE_EVENT, PreviewPrograms.TYPE_CHANNEL, or PreviewPrograms.TYPE_CLIP. Other types not supported. Yes
title
COLUMN_WEIGHT
Positioning of tile in the row. Fallback is program insert order if COLUMN_WEIGHT is not set. No
title
COLUMN_TITLE
Title of event, displayed on content tile and mini-details. A Yes
short_description
COLUMN_SHORT_DESCRIPTION
Event description, displayed in mini-details. C Yes
poster_art_uri
COLUMN_POSTER_ART_URI
16:9 image used in both the content tile and background image when live preview is not available. F, H Yes
intent_uri
COLUMN_INTENT_URI
Action taken when user selects content. This should lead to full-screen playback of the event. Yes
start_time_utc_millis
COLUMN_START_TIME_UTC_MILLIS
Date and start time of event, displayed in mini-details. Also use to determine LIVE badging. B, G Yes
end_time_utc_millis
COLUMN_END_TIME_UTC_MILLIS
End time of event, displayed in mini-details. Also used to determine LIVE badging. B, G Yes
live
COLUMN_LIVE
Determines if LIVE badging should be displayed whether or not the content is currently live (true) or a rebroadcast of previously live events (false). E Yes
preview_video_uri
COLUMN_PREVIEW_VIDEO_URI
When a content tile is in focus, video renders in the upper-right corner of the screen. Referred to as a "live preview." H Yes
logo_uri
COLUMN_LOGO_URI
Application logo – currently not supported via TIF but supported via “Provider Attribution” section listed above. H No
content_rating
COLUMN_CONTENT_RATING
Parental control rating (for display purposes only). B No
interaction_count
COLUMN_INTERACTION_COUNT
For PreviewPrograms.TYPE_CLIP only. The number of times viewers have interacted with this content. Will be displayed in the mini-details. B No^
internal_provider_data
COLUMN_INTERNAL_PROVIDER_DATA
JSON text containing two optional fields: up_next and
original_air_time.
For use with PreviewPrograms.TYPE_CHANNEL only. A string containing the title of the content that will play following the current program, displayed in the mini-details.

original_air_time. For use with rebroadcast content. A string containing the time the currently playing content was originally broadcast, displayed in the mini-details.
C No^

^ Available for development now, with presentation support coming soon.

You can leverage PreviewProgram.Builder to create the PreviewProgram object on Fire OS 7 devices. For earlier versions of Fire OS, you must manually create ContentValues. Review the Code Samples section below for reference.

Content Support: Events

For events with a known schedule (e.g. sporting event), use the PreviewProgram.TYPE_EVENT type with the live flag set to true and the start and end times populated. If an event program has a known schedule, like a sports event, we recommend that you push both the start and end time as metadata to take full advantage of advanced features that Fire TV supports. Note the following:

  1. Fire TV will display events scheduled to air within 7 days and automatically remove them when their end time has passed. As a result, you can push events taking place well beyond these 7 days without worrying about the events being displayed too early or not being removed on time.
  2. Currently airing events will receive a LIVE badge on the tile to inform user of the airing status. The LIVE badge will be hidden when it's not airing.
  3. If valid start and end times are provided, a red progress bar will appear at the bottom of the event tile to inform user of the event's progress.

For instant events (e.g. live video blog), use the PreviewProgram.TYPE_EVENT type with the live flag set to true and the start and end times populated with Long.MIN_VALUE and Long.MAX_VALUE accordingly. Removing this type of content from the database will remove the content from the UI.

Content Support: Rebroadcasts

For rebroadcasts of live content (e.g. re-airings of a previous sporting event), use the PreviewProgram.TYPE_EVENT with the live flag set to false and the start and end times populated with Long.MIN_VALUE and Long.MAX_VALUE accordingly. Removing this type of content from the database will remove the content from the UI. If a customer exits and re-enters through the Fire TV UI, a best practice is to begin playback at the customer’s last watched point.

Content Support: Short Form Clips

For short clips of content (e.g. sporting event highlights), use the PreviewProgram.TYPE_CLIP with the live flag set to false and the start and end times populated with Long.MIN_VALUE and Long.MAX_VALUE accordingly. The interaction_count field can be set in the mini-details with the number of times viewers have interacted with this content. Removing this type of content from the database will remove the content from the UI.

Content Support: Linear Channels

Developers can include linear channels (programs scheduled at a certain time, similar to traditional or cable television) as part of this integration under a simplified feature set. If your app aims to integrate only linear channels, Live TV Integration: Linear may be a better suited integration path.

Use the PreviewProgram.TYPE_CHANNEL type with the live flag set to true. At a minimum, the description and poster art must reflect the attributes of the channel. However, we strongly recommend you refresh these fields for currently airing content and add the next airing program information to the up_next field. Selecting the tile will ingress to full screen playback at the latest timestamp (not last watched). Removing this type of content from the database will remove the content from the UI.

Best Practices

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

General

  • Provide a friction-free sign-up to encourage trials where applicable. Examples include reducing registration forms on the application, or use mobile to sign up.
  • Mention this integration as part of your download page and release notes so that customers understand the new feature availability on Fire TV.
  • Before interacting with databases, always check for the device's feature compatibility. This will ensure your event contents are correctly displayed across all Fire TV devices.
  • Optimize your deeplinking flow to begin full-screen playback in less than 2.5 seconds.

Content Insertion

  • We recommend that you construct ContentValues of live events manually instead of using support library's helper functions (e.g., PreviewProgram.Builder) when inserting them into the database.
  • Insert a minimum of 5 tiles to completely fill the carousel. Fire TV will hide your row if there are less than 4 PreviewPrograms available. Consider adding rebroadcasts, short form clips, or linear channels to maintain the minimum at all times.
  • Provide all required metadata for live event programs. Refer to Programming Metadata Attributes for details regarding the program type, start time, end time, and Live badge.
  • Supply a displayable event name for the COLUMN_TITLE column. Fire TV displays up to 16 alphanumeric, or 8-10 full-width characters for the program tile.
  • Support live event previews in browse to drive engagement.

Refreshing Content

  • Use JobScheduler or WorkManager to periodically check that events are accurate and there are a sufficient number of events displayed for the next 7 days. This will ensure your event content in the browse experiences is always rich and in sync with the real entitled event content, even if your app isn't active in the foreground.
  • Push future-scheduled airing events ahead of time to minimize frequency of database operations. Fire TV will cap a maximum of 15 tiles per event row for performance optimization, and will remove ended events from the carousel within 5 minutes after passing its end time. Your application only needs to remove expired live event content in the next periodic sync.

Code Samples

Here are some common implementations for live events.

Android Manifest

<!-- Required. This service is for using JobScheduler to sync
     Live Event data periodically -->
<service
    android:name=".SampleJobService"
    android:permission="android.permission.BIND_JOB_SERVICE"
    android:exported="true" />


<!-- Required. This receiver is to trigger sync job schedule after reboot. -->
<receiver android:name=".rich.RichBootReceiver">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

<!-- This service is for playing preview. Only needed when supporting
     preview playback in Fire TV UI through TvView-->
<service android:name=".PreviewInputService"
    android:permission="android.permission.BIND_TV_INPUT">
    <!-- Required filter used by the system to launch our account service. -->
    <intent-filter>
        <action android:name="android.media.tv.TvInputService" />
    </intent-filter>
    <!-- An XML file which describes this input. -->
    <meta-data
        android:name="android.media.tv.input"
        android:resource="@xml/previewinputservice" />
</service>

Check Feature Compatibility

// Amazon marker to identify given device has feature backported
private final static String AMAZON_SYS_FEATURE_KEY =
  "com.amazon.feature.fos7_tv_provider";

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
  // This feature is garuanteed suported starting Android O (API 26) version
  .....
} else if (isPreviewProgramBackportedOnFOS(context))(
  // This feature is supported by Amazon on early FOS devices through backport
  .....
}

public static boolean isPreviewProgramBackportedOnFOS(Context context) {
  PackageManager pm = context.getPackageManager();
  return pm.hasSystemFeature(AMAZON_SYS_FEATURE_KEY) &&
    pm.hasSystemFeature(AMAZON_SYS_FEATURE_KEY, 1);
}
// Amazon marker to identify given device has feature backported
private const val AMAZON_SYS_FEATURE_KEY = "com.amazon.feature.fos7_tv_provider"

private fun checkFeatureCompatibility(context: Context) {
    when {
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
            // This feature is guaranteed supported starting Android O (API 26) version
        }
        isPreviewProgramBackportedOnFOS(context) -> {
            // This feature is supported by Amazon on early FOS devices through backport
        }
        else -> {
            // Feature is not available
        }
    }
}

public fun isPreviewProgramBackportedOnFOS(context: Context): Boolean {
    val pm = context.packageManager;
    return pm.hasSystemFeature(AMAZON_SYS_FEATURE_KEY) &&
            pm.hasSystemFeature(AMAZON_SYS_FEATURE_KEY, 1)
}

Insert Preview Channel

public void buildPreviewChannel() {
    Channel.Builder builder = new Channel.Builder();
    builder.setType(TvContractCompat.Channels.TYPE_PREVIEW)
            .setDisplayName("SampleProviderChannel")
            .setAppLinkIntentUri(Uri.REQUIRED);/* should be the intent to
                                               launch 3P's main screen */
    Channel newChannel = builder.build();
    ContentValues cv = newChannel.toContentValues();
    Uri channelUri = resolver.insert(TvContractCompat.Channels.CONTENT_URI, cv);
}
fun buildPreviewChannel(context: Context) {
    val newChannel = Channel.Builder()
        .setType(TvContractCompat.Channels.TYPE_PREVIEW)
        .setDisplayName("SampleProviderChannel")
        .setAppLinkIntentUri(Uri.REQUIRED) // should be the intent to launch 3P's main screen        .build()

    val cv: ContentValues = newChannel.toContentValues()
    val channelUri: Uri? = context.contentResolver.insert(TvContractCompat.Channels.CONTENT_URI, cv)
}

Create Live Event

public static ContentValues createLiveEventContentValues(Context context,
  long channelId) {

 ComponentName componentName = new ComponentName(context, PreviewVideoInputService.class);
 Uri previewVideoUri = TvContractCompat.buildPreviewProgramUri(1)
       .buildUpon()
       .appendQueryParameter("input", TvContractCompat.buildInputId(componentName))
       .build();
       
  TvContentRating[] ratings = new TvContentRating[1];
  ratings[0] = TvContentRating.createRating("com.android.tv.dummy",
    "US_TV_DUMMY",
    "US_TV_PG_DUMMY",
    "US_TV_D_DUMMY");

  /* Note: Make sure you test before publishing. Example:
       adb shell
       am start -W -a android.intent.action.VIEW -d "example://test/blablabla?e=1"
  */
  Intent deeplinkIntent = new Intent("android.intent.action.VIEW",
    Uri.parse("example://test/blablabla?e=1"));

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    Log.d(Utils.DEBUG_TAG, ">=26 Android build. Support live event!");
    PreviewProgram.Builder liveEventBuilder = new PreviewProgram.Builder();
    liveEventBuilder.setChannelId(channelId)
      .setLive(true)
      .setType(TvContractCompat.PreviewPrograms.TYPE_EVENT)
      .setTitle("Dummy Event Title")
      .setDescription("Dummy Event description")
      .setStartTimeUtcMillis(10000000)
      .setEndTimeUtcMillis(20000000)
      .setPosterArtUri(Uri.parse("http://placekitten.com/200/300"))
      .setLogoUri(Uri.parse("http://provider.logo.uri"))
      .setIntent(deeplinkIntent)
      .setPreviewVideoUri(previewVideoUri)
      .setContentRatings(ratings);
    return liveEventBuilder.build().toContentValues();
  } else if (Utils.isPreviewProgramBackportedOnFOS(context)) {
    Log.d(Utils.DEBUG_TAG, "Backported feature detected! Supports live event!");

    // Align with the internal logic of setIntent() in PreviewProgram.Builder()
    Uri deeplinkIntentUri = Uri.parse(deeplinkIntent.toUri(URI_INTENT_SCHEME));

    /* Manually create ContentValues for build < 26. Can't use
       PreviewProgramBuilder because toContentValues() method
       internally removes critical keys for build < 26, which
       will cause crash */
    ContentValues cv = new ContentValues();
    cv.put(TvContractCompat.PreviewPrograms.COLUMN_CHANNEL_ID, channelId);
    cv.put(TvContractCompat.PreviewPrograms.COLUMN_LIVE, true);
    cv.put(TvContractCompat.PreviewPrograms.COLUMN_TYPE,
      TvContractCompat.PreviewPrograms.TYPE_EVENT);
    cv.put(TvContractCompat.PreviewPrograms.COLUMN_TITLE, "Dummy Event Title");
    cv.put(TvContractCompat.PreviewPrograms.COLUMN_SHORT_DESCRIPTION,
      "Dummy Event description");
    cv.put(TvContractCompat.PreviewPrograms.COLUMN_START_TIME_UTC_MILLIS,
      10000000);
    cv.put(TvContractCompat.PreviewPrograms.COLUMN_END_TIME_UTC_MILLIS,
      20000000);
    cv.put(TvContractCompat.PreviewPrograms.COLUMN_POSTER_ART_URI,
      "http://placekitten.com/200/300");
    cv.put(TvContractCompat.PreviewPrograms.COLUMN_LOGO_URI,
      "http://provider.logo.uri");
    cv.put(TvContractCompat.PreviewPrograms.COLUMN_INTENT_URI,
      (deeplinkIntentUri.toString()));
    cv.put(TvContractCompat.PreviewPrograms.COLUMN_PREVIEW_VIDEO_URI,
      previewVideoUri.toString());
    cv.put(TvContractCompat.PreviewPrograms.COLUMN_CONTENT_RATING,
      contentRatingsToString(ratings));
    return cv;
  } else {
    Log.d(Utils.DEBUG_TAG, "System build is not supporting live event");
    return null;
  }
}
fun createLiveEventContentValues(context: Context, channelId: Long): ContentValues? {

    val componentName = new ComponentName(context, PreviewVideoInputService.class)  
    val previewVideoUri: Uri = TvContractCompat.buildPreviewProgramUri(1)
        .buildUpon()
        .appendQueryParameter("input", TvContractCompat.buildInputId(componentName))
        .build()
  
    val ratings = arrayOf<TvContentRating>(
        TvContentRating.createRating(
            "com.android.tv.dummy",
            "US_TV_DUMMY",
            "US_TV_PG_DUMMY",
            "US_TV_D_DUMMY"
        )
    )

    /* Note: Make sure you test before publishing. Example:
       adb shell
       am start -W -a android.intent.action.VIEW -d "example://test/blablabla?e=1"
  */
    val deeplinkIntent = Intent(
        "android.intent.action.VIEW",
        Uri.parse("example://test/blablabla?e=1")
    )
    return when {
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.O -> {
            Log.d(TAG, ">=26 Android build. Support live event!")
            PreviewProgram.Builder()
                .setChannelId(channelId)
                .setLive(true)
                .setType(TvContractCompat.PreviewPrograms.TYPE_EVENT)
                .setTitle("Dummy Event Title")
                .setDescription("Dummy Event description")
                .setStartTimeUtcMillis(10000000)
                .setEndTimeUtcMillis(20000000)
                .setPosterArtUri(Uri.parse("http://placekitten.com/200/300"))
                .setLogoUri(Uri.parse("http://provider.logo.uri"))
                .setIntent(deeplinkIntent)
                .setPreviewVideoUri(previewVideoUri)
                .setContentRatings(ratings)
                .build()
                .toContentValues()
        }
        isPreviewProgramBackportedOnFOS(context) -> {
            Log.d(TAG, "Backported feature detected! Supports live event!")

            // Align with the internal logic of setIntent() in PreviewProgram.Builder()
            val deeplinkIntentUri: Uri = Uri.parse(deeplinkIntent.toUri(URI_INTENT_SCHEME))

            // Manually create ContentValues for build < 26. Can't use
            // PreviewProgramBuilder because toContentValues() method
            // internally removes critical keys for build < 26, which
            // will cause crash
            ContentValues().apply {
                put(TvContractCompat.PreviewPrograms.COLUMN_CHANNEL_ID, channelId)
                put(TvContractCompat.PreviewPrograms.COLUMN_LIVE, true)
                put(
                    TvContractCompat.PreviewPrograms.COLUMN_TYPE,
                    TvContractCompat.PreviewPrograms.TYPE_EVENT
                )
                put(TvContractCompat.PreviewPrograms.COLUMN_TITLE, "Dummy Event Title")
                put(
                    TvContractCompat.PreviewPrograms.COLUMN_SHORT_DESCRIPTION,
                    "Dummy Event description"
                )
                put(
                    TvContractCompat.PreviewPrograms.COLUMN_START_TIME_UTC_MILLIS,
                    10000000
                )
                put(
                    TvContractCompat.PreviewPrograms.COLUMN_END_TIME_UTC_MILLIS,
                    20000000
                )
                put(
                    TvContractCompat.PreviewPrograms.COLUMN_POSTER_ART_URI,
                    "http://placekitten.com/200/300"
                )
                put(
                    TvContractCompat.PreviewPrograms.COLUMN_LOGO_URI,
                    "http://provider.logo.uri"
                )
                put(
                    TvContractCompat.PreviewPrograms.COLUMN_INTENT_URI,
                    deeplinkIntentUri.toString()
                )
                put(
                    TvContractCompat.PreviewPrograms.COLUMN_PREVIEW_VIDEO_URI,
                    previewVideoUri.toString()
                )
                put(
                    TvContractCompat.PreviewPrograms.COLUMN_CONTENT_RATING,
                    contentRatingsToString(ratings)
                )
            }
        }
        else -> {
            Log.d(TAG, "System build is not supporting live event")
            null
        }
    }
}

private const val TAG = "MyTag"

// Amazon marker to identify given device has feature backported
private const val AMAZON_SYS_FEATURE_KEY = "com.amazon.feature.fos7_tv_provider"

public fun isPreviewProgramBackportedOnFOS(context: Context): Boolean {
    val pm = context.packageManager;
    return pm.hasSystemFeature(AMAZON_SYS_FEATURE_KEY) &&
            pm.hasSystemFeature(AMAZON_SYS_FEATURE_KEY, 1)
}

fun contentRatingsToString(contentRatings: Array<TvContentRating>?): String? {
    if (contentRatings == null || contentRatings.isEmpty()) {
        return null
    }
    val DELIMITER = ","
    val ratings = StringBuilder(contentRatings[0].flattenToString())
    for (i in 1 until contentRatings.size) {
        ratings.append(DELIMITER)
        ratings.append(contentRatings[i].flattenToString())
    }
    return ratings.toString()
}

Insert Content

ContentValues[] liveEventsArray = < Array of ContentValues of PreviewProgram >
  resolver.bulkInsert(TvContractCompat.PreviewPrograms.CONTENT_URI, liveEventsArray);
fun insertLiveEventContent(context: Context) {
    val liveEventsArray = arrayOf<ContentValues>()// Array of ContentValues of PreviewProgram
    context.contentResolver.bulkInsert(
        TvContractCompat.PreviewPrograms.CONTENT_URI,
        liveEventsArray
    )
}

Update Content

ContentValues updateValues = < values of a PreviewProgram to update >
  resolver.update(TvContractCompat.buildPreviewProgramUri( < Id of the preview program to update > ), updateValues, null, null);
fun updateLiveEventContent(context: Context, programIdToUpdate: Long, updateValues: ContentValues) {
    context.contentResolver.update(TvContractCompat.buildPreviewProgramUri(programIdToUpdate), updateValues, null, null);
}

Last updated: Oct 10, 2022