跳转到相应内容

最常访问

最近访问

navigation

Working with Channel Data

Your TV input must provide Electronic Program Guide (EPG) data for at least one channel in its setup activity. You should also periodically update that data, with consideration for the size of the update and the processing thread that handles it. Additionally, you can provide app links for channels that guide the user to related content and activities. This lesson discusses creating and updating channel and program data on the system database with these considerations in mind.

 

Get Permission

In order for your TV input to work with EPG data, it must declare the read and write permissions in its Android manifest file as follows:

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

Register Channels in the Database

The Android TV system database maintains records of channel data for TV inputs. In your setup activity, for each of your channels, you must map your channel data to the following fields of the TvContract.Channels class:

Although the TV input framework is generic enough to handle both traditional broadcast and over-the-top (OTT) content without any distinction, you may want to define the following columns in addition to those above to better identify traditional broadcast channels:

If you want to provide app link details for your channels, you need to update some additional fields. For more information on app link fields, see Add App Link Information.

For internet streaming based TV inputs, assign your own values to the above accordingly so that each channel can be identified uniquely.

Pull your channel metadata (in XML, JSON, or whatever) from your backend server, and in your setup activity map the values to the system database as follows:

ContentValues values = new ContentValues();

values.put(Channels.COLUMN_DISPLAY_NUMBER, channel.mNumber);
values.put(Channels.COLUMN_DISPLAY_NAME, channel.mName);
values.put(Channels.COLUMN_ORIGINAL_NETWORK_ID, channel.mOriginalNetworkId);
values.put(Channels.COLUMN_TRANSPORT_STREAM_ID, channel.mTransportStreamId);
values.put(Channels.COLUMN_SERVICE_ID, channel.mServiceId);
values.put(Channels.COLUMN_VIDEO_FORMAT, channel.mVideoFormat);

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

In the example above, channel is an object which holds channel metadata from the backend server.

Present Channel and Program Information

The system TV app presents channel and program information to users as they flip through channels, as shown in figure 1. To make sure the channel and program information works with the system TV app's channel and program information presenter, follow the guidelines below.

  1. Channel number (COLUMN_DISPLAY_NUMBER)
  2. Icon (android:icon in the TV input's manifest)
  3. Program description (COLUMN_SHORT_DESCRIPTION)
  4. Program title (COLUMN_TITLE)
  5. Channel logo (TvContract.Channels.Logo)
    • Use the color #EEEEEE to match the surrounding text
    • Don't include padding
  6. Poster art (COLUMN_POSTER_ART_URI)
    • Aspect ratio between 16:9 and 4:3

Figure 1. The system TV app channel and program information presenter.

The system TV app provides the same information through the program guide, including poster art, as shown in figure 2.

Figure 2. The system TV app program guide.

Update Channel Data

When updating existing channel data, use the update() method instead of deleting and re-adding the data. You can identify the current version of the data by using Channels.COLUMN_VERSION_NUMBER and Programs.COLUMN_VERSION_NUMBER when choosing the records to update.

Note: Adding channel data to the ContentProvider can take time. Only add current programs (those within two hours of the current time) when you update, and use a Sync Adapter to update the rest of the channel data in the background. See the Android TV Live TV Sample App for an example.

Batch Loading Channel Data

When updating the system database with a large amount of channel data, use the ContentResolver applyBatch() or bulkInsert() method. Here's an example using applyBatch():

ArrayList<ContentProviderOperation> ops = new ArrayList<>();
int programsCount = mChannelInfo.mPrograms.size();
for (int j = 0; j < programsCount; ++j) {
    ProgramInfo program = mChannelInfo.mPrograms.get(j);
    ops.add(ContentProviderOperation.newInsert(
            TvContract.Programs.CONTENT_URI)
            .withValues(programs.get(j))
            .withValue(Programs.COLUMN_START_TIME_UTC_MILLIS,
                    programStartSec * 1000)
            .withValue(Programs.COLUMN_END_TIME_UTC_MILLIS,
                    (programStartSec + program.mDurationSec) * 1000)
            .build());
    programStartSec = programStartSec + program.mDurationSec;
    if (j % 100 == 99 || j == programsCount - 1) {
        try {
            getContentResolver().applyBatch(TvContract.AUTHORITY, ops);
        } catch (RemoteException | OperationApplicationException e) {
            Log.e(TAG, "Failed to insert programs.", e);
            return;
        }
        ops.clear();
    }
}

Processing Channel Data Asynchronously

Data manipulation, such as fetching a stream from the server or accessing the database, should not block the UI thread. Using an AsyncTask is one way to perform updates asynchronously. For example, when loading channel info from a backend server, you can use AsyncTask as follows:

private static class LoadTvInputTask extends AsyncTask<Uri, Void, Void>> {

    private Context mContext;

    public LoadTvInputTask(Context context) {
        mContext = context;
    }

    @Override
    protected Void doInBackground(Uri... uris) {
        try {
            fetchUri(uris[0]);
        } catch (IOException e) {
          Log.d(“LoadTvInputTask”, “fetchUri error”);
        }
        return null;
    }

    private void fetchUri(Uri videoUri) throws IOException {
        InputStream inputStream = null;
        try {
            inputStream = mContext.getContentResolver().openInputStream(videoUri);
            XmlPullParser parser = Xml.newPullParser();
            try {
                parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
                parser.setInput(inputStream, null);
                sTvInput = ChannelXMLParser.parseTvInput(parser);
                sSampleChannels = ChannelXMLParser.parseChannelXML(parser);
            } catch (XmlPullParserException e) {
                e.printStackTrace();
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }
}

If you need to update EPG data on a regular basis, consider using a Sync Adapter or JobScheduler to run the update process during idle time, such as every day at 3:00 a.m. See the Android TV live TV sample app for an example.

Other techniques to separate the data update tasks from the UI thread include using the HandlerThread class, or you may implement your own using Looper and Handler classes. See Processes and Threads for more information.

Channels can use app links to let users easily launch a related activity while they are watching channel content. Channel apps use app links to extend user engagement by launching activities that show related information or additional content. For example, you can use app links to do the following:

App links are displayed when the user presses Select to show the TV menu while watching channel content.

Figure 1. An example app link displayed on the Channels row while channel content is shown.

When the user selects the app link, the system starts an activity using an intent URI specified by the channel app. Channel content continues to play while the app link activity is active. The user can return to the channel content by pressing Back.

Provide App Link Channel Data

Android TV automatically creates an app link for each channel, using information from the channel data. To provide app link information, specify the following details in your TvContract.Channels fields:

Figure 2. App link details.

If the channel data doesn't specify app link information, the system creates a default app link. The system chooses default details as follows:

You specify app link details for your channels in your app's setup activity. You can update these app link details at any point, so if an app link needs to match channel changes, update app link details and call ContentResolver.update() as needed. For more details on updating channel data, see Update Channel Data.

此网站会使用 Cookie 来存储您在此网站上指定的语言和显示选项偏好设置。

获取最新的 Android Developers 资讯和提示,助您在 Google Play 上取得成功。

* 必填字段

成功!

在微信上关注 Google Developers

要以浏览此网站吗?

您请求访问的是网页,但是您为此网站设置的语言偏好为

要更改您的语言偏好设置并以浏览此网站吗?如果以后您想要更改语言偏好设置,请使用每个页面底部的语言菜单。

该类需要 或更高的 API 级别

此文档已被隐藏,因为您为该文档选择的 API 级别是 。您可以使用左侧导航栏上方的选择器来更改文档的 API 级别。

要详细了解如何根据您的应用需求指定 API 级别,请参阅支持不同平台版本

Take a short survey?
Help us improve the Android developer experience. (April 2018 — Developer Survey)