android编辑频道,使用频道数据  |  Android 开发者  |  Android Developers

TV 输入必须在其设置 Activity 中至少提供一个频道的电子收视指南 (EPG) 数据。您还应定期更新该数据,需要考虑更新的大小以及负责执行更新的处理线程。此外,您还可以提供频道的应用链接,将用户引向相关的内容和 Activity。本节课介绍了如何在系统数据库中创建和更新频道和节目数据,同时考虑到这些因素。

请试用 TV 输入服务示例应用。

获取权限

为使您的 TV 输入支持 EPG 数据,它必须在其 Android 清单文件中声明写入权限,如下所示:

注意:READ_EPG_DATA 权限已在 Android M (API 23) 中弃用,不再需要。

在数据库中注册频道

Android TV 系统数据库维护 TV 输入的频道数据记录。在设置 Activity 中,您必须将每个频道的频道数据映射到

虽然 TV 输入框架非常通用,对传统播放内容和 OTT 服务内容的处理没有任何区别,但除了上面几列之外,您可能还需要定义下面几列,以便更好地标识传统播放频道:

如需提供频道的应用链接详细信息,您需要更新一些其他字段。如需详细了解应用链接字段,请参阅添加应用链接信息。

对于基于互联网流式传输的 TV 输入,请相应地为上面的字段分配您自己的值,以便可以唯一地标识每个频道。

从后端服务器提取频道元数据(采用 XML、JSON 或其他任何格式),然后在设置 Activity 中将值映射到系统数据库,如下所示:

Kotlin

val values = ContentValues().apply {

put(TvContract.Channels.COLUMN_DISPLAY_NUMBER, channel.number)

put(TvContract.Channels.COLUMN_DISPLAY_NAME, channel.name)

put(TvContract.Channels.COLUMN_ORIGINAL_NETWORK_ID, channel.originalNetworkId)

put(TvContract.Channels.COLUMN_TRANSPORT_STREAM_ID, channel.transportStreamId)

put(TvContract.Channels.COLUMN_SERVICE_ID, channel.serviceId)

put(TvContract.Channels.COLUMN_VIDEO_FORMAT, channel.videoFormat)

}

val uri = context.contentResolver.insert(TvContract.Channels.CONTENT_URI, values)Java

ContentValues values = new ContentValues();

values.put(Channels.COLUMN_DISPLAY_NUMBER, channel.number);

values.put(Channels.COLUMN_DISPLAY_NAME, channel.name);

values.put(Channels.COLUMN_ORIGINAL_NETWORK_ID, channel.originalNetworkId);

values.put(Channels.COLUMN_TRANSPORT_STREAM_ID, channel.transportStreamId);

values.put(Channels.COLUMN_SERVICE_ID, channel.serviceId);

values.put(Channels.COLUMN_VIDEO_FORMAT, channel.videoFormat);

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

在上面的示例中,channel 是一个对象,用于保存来自后端服务器的频道元数据。

呈现频道和节目信息

当用户浏览频道时,系统 TV 应用会向他们呈现频道和节目信息,如图 1 所示。如需确保频道和节目信息可以与系统 TV 应用的频道和节目信息 Presenter 一起使用,请遵循以下准则。

8e3ababfe6d68223a1de749c842813c2.png

图 1. 系统 TV 应用的频道和节目信息 Presenter。

系统 TV 应用可通过收视指南提供相同的信息(包括海报图片),如图 2 所示。

d3a43d516d682113bf1663ba786981a1.png

图 2. 系统 TV 应用的收视指南。

更新频道数据

注意:向 EpgSyncJobService 配置为在后台更新其余频道数据时,才能添加当前节目(在当前时间的两小时以内的节目)。如需查看示例,请参阅 Android TV Live TV 示例应用。

批量加载频道数据

Kotlin

val ops = ArrayList()

val programsCount = channelInfo.mPrograms.size

channelInfo.mPrograms.forEachIndexed { index, program ->

ops += ContentProviderOperation.newInsert(

TvContract.Programs.CONTENT_URI).run {

withValues(programs[index])

withValue(TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS, programStartSec * 1000)

withValue(

TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS,

(programStartSec + program.durationSec) * 1000

)

build()

}

programStartSec += program.durationSec

if (index % 100 == 99 || index == programsCount - 1) {

try {

contentResolver.applyBatch(TvContract.AUTHORITY, ops)

} catch (e: RemoteException) {

Log.e(TAG, "Failed to insert programs.", e)

return

} catch (e: OperationApplicationException) {

Log.e(TAG, "Failed to insert programs.", e)

return

}

ops.clear()

}

}Java

ArrayList ops = new ArrayList<>();

int programsCount = channelInfo.mPrograms.size();

for (int j = 0; j < programsCount; ++j) {

ProgramInfo program = channelInfo.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.durationSec) * 1000)

.build());

programStartSec = programStartSec + program.durationSec;

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

}

}

异步处理频道数据

数据操作(如从服务器获取流或访问数据库)不应阻塞界面线程。使用

Kotlin

private class LoadTvInputTask(val context: Context) : AsyncTask() {

override fun doInBackground(vararg uris: Uri) {

try {

fetchUri(uris[0])

} catch (e: IOException) {

Log.d("LoadTvInputTask", "fetchUri error")

}

}

@Throws(IOException::class)

private fun fetchUri(videoUri: Uri) {

context.contentResolver.openInputStream(videoUri).use { inputStream ->

Xml.newPullParser().also { parser ->

try {

parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false)

parser.setInput(inputStream, null)

sTvInput = ChannelXMLParser.parseTvInput(parser)

sSampleChannels = ChannelXMLParser.parseChannelXML(parser)

} catch (e: XmlPullParserException) {

e.printStackTrace()

}

}

}

}

}Java

private static class LoadTvInputTask extends AsyncTask {

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

}

}

}

}

如果您需要定期更新 EPG 数据,不妨考虑在空闲时间(如每天凌晨 3:00)使用 WorkManager 来运行更新流程。

将数据更新任务与界面线程分开的其他方法包括使用 进程和线程。

添加应用链接信息

频道可以使用应用链接来让用户在观看频道内容时轻松启动相关的 Activity。利用应用链接,频道应用可以启动显示相关信息或其他内容的 Activity,从而提升用户互动度。例如,您可以使用应用链接执行以下操作:

引导用户发现和购买相关内容。

提供有关当前播放内容的其他信息。

在观看剧集内容时,开始观看电视剧的下一集。

在不中断内容播放的情况下,让用户与内容互动(例如,对内容进行评分或评价)。

如果用户在观看频道内容时按选择以显示 TV 菜单,就会显示应用链接。

045b0e36a6374f9de2a2593ecea2a474.png

图 1. 显示频道内容时,在频道行上显示的应用链接示例。

当用户选择应用链接时,系统会使用由频道应用指定的 intent URI 启动 Activity。当应用链接 Activity 处于活动状态时,频道内容继续播放。用户可以按返回以返回频道内容。

提供应用链接频道数据

Android TV 会使用来自频道数据的信息自动创建每个频道的应用链接。如需提供应用链接信息,请在

2005267f35815d9d7cb111eb825f0300.png

图 2. 应用链接详细信息。

如果频道数据未指定应用链接信息,则系统会创建一个默认应用链接。系统会选择默认详细信息,具体说明如下:

对于 intent URI (

对于描述性文字 (app-name”。如果未定义可行的应用链接 intent URI,系统会使用“No link available”。

对于强调色 (

对于海报图片 (

对于标志图标 (

您可以在应用的设置 Activity 中指定频道的应用链接详细信息。您可以随时更新这些应用链接详细信息,所以如果某个应用链接需要与频道变更保持一致,请更新相应的应用链接详细信息并根据需要调用 更新频道数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值