android TV-Working with Channel Data
> 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 channelCOLUMN_DISPLAY_NUMBER
- the displayed channel numberCOLUMN_INPUT_ID
- the ID of the TV input serviceCOLUMN_SERVICE_TYPE
- the channel's service typeCOLUMN_TYPE
- the channel's broadcast standard typeCOLUMN_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 IDCOLUMN_SERVICE_ID
- the service IDCOLUMN_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.
相關文章
- ORACLE TNS Io異常End of TNS data channel&ORA-12518Oracle
- go : channel , queue , 程式管理 , 關閉channel ?Go
- 6 Java NIO Channel to Channel Transfers-翻譯Java
- Go – Channel 原理Go
- go channel例子Go
- go channel ->同步Go
- c# channelC#
- Buffer和Channel
- 深入原始碼學習 android data binding 之:data binding 註解原始碼Android
- Golang 的 Channel 控制Golang
- Java NIO Channel 使用Java
- Go channel 的妙用Go
- go併發 - channelGo
- go channel問題Go
- ALLOCATE CHANNEL FOR MAINTENANCE 命令AINaN
- Go channel 介紹Go
- Golang 的 Channel 行為Golang
- Golang通道Channel詳解Golang
- golang-channel詳解Golang
- NIO(四)channel總結
- golang中channel的用法Golang
- golang開發:channel使用Golang
- Java NIO 之 Channel(通道)Java
- Ethernet Channel(埠聚合)
- Java - NIO之Channel(FileChannel)Java
- go嘗試從channel c接收資料,並檢查channel是否關閉Go
- Android 13及以上如何備份Android/data目錄中的檔案Android
- Java NIO - Channel 與 SelectorJava
- 深度解密 Go 語言之 channel解密Go
- 全面解析Flutter Platform Channel原理FlutterPlatform
- 深度解密Go語言之channel解密Go
- Go channel 實現原理分析Go
- Go Channel 詳細介紹Go
- go channel學習筆記Go筆記
- 深入理解Flutter Platform ChannelFlutterPlatform
- Netty Channel原始碼分析Netty原始碼
- Go--關於 goroutine、channelGo
- Java NIO系列教程(二) ChannelJava