您的位置:首页 > 移动开发 > Android开发

android TV-Working with Channel Data

2016-01-22 12:13 741 查看
> 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.

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" />

> 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:

COLUMN_DISPLAY_NAME
-
the displayed name of the channel
COLUMN_DISPLAY_NUMBER
-
the displayed channel number
COLUMN_INPUT_ID
-
the ID of the TV input service
COLUMN_SERVICE_TYPE
-
the channel's service type
COLUMN_TYPE
-
the channel's broadcast standard type
COLUMN_VIDEO_FORMAT
-
the default video format for the channel

>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:

COLUMN_ORIGINAL_NETWORK_ID
-
the television network ID
COLUMN_SERVICE_ID
-
the service ID
COLUMN_TRANSPORT_STREAM_ID
-
the transport stream ID

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);

> To make sure the channel and program information works with the system TV app's channel and program information presenter, follow the guidelines below.

Channel number (
COLUMN_DISPLAY_NUMBER
)
Icon (
android:icon
in
the TV input's manifest)
Program description (
COLUMN_SHORT_DESCRIPTION
)
Program title (
COLUMN_TITLE
)
Channel logo (
TvContract.Channels.Logo
)

Use the color #EEEEEE to match the surrounding text
Don't include padding

Poster art (
COLUMN_POSTER_ART_URI
)

Aspect ratio between 16:9 and 4:3

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.

> 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();
}
}

> 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.

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. 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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: