На главном экране Android TV рекомендованный контент представлен в виде таблицы каналов и программ. Каждая строка соответствует одному каналу. Канал содержит карточки для всех доступных на нем программ.
В этом документе показано, как добавлять каналы и программы на главный экран, обновлять контент, обрабатывать действия пользователей и обеспечивать наилучшие условия для пользователей. Если вы хотите узнать больше об API, попробуйте практическую работу по главному экрану и посмотрите семинар по Android TV на I/O 2017.
Интерфейс главного экрана
Приложения могут создавать новые каналы, добавлять, удалять и обновлять программы в канале, а также управлять порядком программ в канале. Например, приложение может создать канал "Что нового" и показывать карточки с недавно добавленными программами.
Приложения не могут управлять порядком, в котором каналы появляются на главном экране. Когда приложение создает новый канал, он добавляется в конец списка на главном экране. Пользователь может менять порядок каналов, а также скрывать и показывать их.
Канал "Смотреть дальше"
Канал "Смотреть дальше" – это вторая строка на главном экране, которая находится под строкой приложений. Этот канал создается и поддерживается системой. Ваше приложение может добавлять программы в канал "Смотреть дальше". Подробнее о том, как добавлять программы в канал "Смотреть дальше"…
Каналы приложений
Все каналы, создаваемые приложением, проходят следующий жизненный цикл:
- Пользователь находит канал в вашем приложении и запрашивает его добавление на главный экран.
- Приложение создает канал и добавляет его в
TvProvider(на этом этапе канал не виден). - Приложение запрашивает у системы показ канала.
- Система просит пользователя одобрить новый канал.
- Новый канал появится в последней строке главного экрана.
Канал по умолчанию
Приложение может предлагать пользователю любое количество каналов для добавления на главный экран. Обычно пользователю нужно выбрать и одобрить каждый канал, прежде чем он появится на главном экране. В каждом приложении можно создать один канал по умолчанию. Канал по умолчанию автоматически появляется на главном экране, и пользователю не нужно запрашивать его.
Требования
На главном экране Android TV используются API TvProvider Android для управления каналами и программами, которые создает ваше приложение. Чтобы получить доступ к данным поставщика, добавьте в манифест приложения следующее разрешение:
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
Библиотека поддержки TvProvider упрощает использование поставщика. Добавьте его в зависимости в файле build.gradle:
Яркий
implementation 'androidx.tvprovider:tvprovider:1.0.0'
Kotlin
implementation("androidx.tvprovider:tvprovider:1.0.0")
Чтобы работать с каналами и программами, добавьте в код следующие импорты библиотеки поддержки:
Kotlin
import android.support.media.tv.Channel
import android.support.media.tv.TvContractCompat
import android.support.media.tv.ChannelLogoUtils
import android.support.media.tv.PreviewProgram
import android.support.media.tv.WatchNextProgram
Java
import android.support.media.tv.Channel;
import android.support.media.tv.TvContractCompat;
import android.support.media.tv.ChannelLogoUtils;
import android.support.media.tv.PreviewProgram;
import android.support.media.tv.WatchNextProgram;
Каналы
Первый канал, созданный приложением, становится каналом по умолчанию. Канал по умолчанию автоматически появляется на главном экране. Все остальные каналы, которые вы создаете, должны быть выбраны и приняты пользователем, прежде чем они появятся на главном экране.
Как создать канал
Приложение должно запрашивать у системы показ новых каналов, только когда оно работает в активном режиме. Это предотвратит появление диалогового окна с запросом на добавление канала, когда пользователь работает с другим приложением. Если вы попытаетесь добавить канал в фоновом режиме, метод onActivityResult() вернет код статуса RESULT_CANCELED.
Чтобы создать канал, выполните следующие действия:
Создайте конструктор каналов и задайте его атрибуты. Обратите внимание, что тип канала должен быть
TYPE_PREVIEW. При необходимости добавьте другие атрибуты.Kotlin
val builder = Channel.Builder() // Every channel you create must have the type `TYPE_PREVIEW` builder.setType(TvContractCompat.Channels.TYPE_PREVIEW) .setDisplayName("Channel Name") .setAppLinkIntentUri(uri)Java
Channel.Builder builder = new Channel.Builder(); // Every channel you create must have the type `TYPE_PREVIEW` builder.setType(TvContractCompat.Channels.TYPE_PREVIEW) .setDisplayName("Channel Name") .setAppLinkIntentUri(uri);Вставьте канал в поставщика:
Kotlin
var channelUri = context.contentResolver.insert( TvContractCompat.Channels.CONTENT_URI, builder.build().toContentValues())Java
Uri channelUri = context.getContentResolver().insert( TvContractCompat.Channels.CONTENT_URI, builder.build().toContentValues());Чтобы добавлять программы на канал, вам нужно сохранить идентификатор канала. Извлеките идентификатор канала из возвращенного URI:
Kotlin
var channelId = ContentUris.parseId(channelUri)Java
long channelId = ContentUris.parseId(channelUri);Добавьте логотип канала. Используйте
UriилиBitmap. Значок логотипа должен быть непрозрачным и иметь размер 80 x 80 dp. Оно показывается в круглой маске:
Kotlin
// Choose one or the other storeChannelLogo(context: Context, channelId: Long, logoUri: Uri) // also works if logoUri is a URL storeChannelLogo(context: Context, channelId: Long, logo: Bitmap)Java
// Choose one or the other storeChannelLogo(Context context, long channelId, Uri logoUri); // also works if logoUri is a URL storeChannelLogo(Context context, long channelId, Bitmap logo);Создайте канал по умолчанию (необязательно). При создании первого канала в приложении вы можете сделать его каналом по умолчанию, чтобы он сразу появлялся на главном экране без каких-либо действий со стороны пользователя. Любые другие созданные вами каналы не будут видны, пока пользователь явно не выберет их.
Kotlin
TvContractCompat.requestChannelBrowsable(context, channelId)Java
TvContractCompat.requestChannelBrowsable(context, channelId);Сделайте так, чтобы канал по умолчанию появлялся до открытия приложения. Для этого добавьте
BroadcastReceiver, который будет отслеживать действиеandroid.media.tv.action.INITIALIZE_PROGRAMS, отправляемое главным экраном после установки приложения:<receiver android:name=".RunOnInstallReceiver" android:exported="true"> <intent-filter> <action android:name="android.media.tv.action.INITIALIZE_PROGRAMS" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver>При установке приложения из неизвестного источника во время разработки вы можете протестировать этот шаг, активировав намерение через adb, где your.package.name/.YourReceiverName – это
BroadcastReceiverвашего приложения:adb shell am broadcast -a android.media.tv.action.INITIALIZE_PROGRAMS -n \ your.package.name/.YourReceiverNameВ редких случаях приложение может получить широковещательное сообщение в момент запуска. Убедитесь, что ваш код не пытается добавить канал по умолчанию несколько раз.
Обновление канала
Обновление каналов выполняется почти так же, как и их создание.
Используйте другой атрибут Channel.Builder, чтобы задать атрибуты, которые нужно изменить.
Обновите канал с помощью ContentResolver. Используйте идентификатор канала, который вы сохранили, когда канал был добавлен:
Kotlin
context.contentResolver.update(
TvContractCompat.buildChannelUri(channelId),
builder.build().toContentValues(),
null,
null
)
Java
context.getContentResolver().update(TvContractCompat.buildChannelUri(channelId),
builder.build().toContentValues(), null, null);
Чтобы обновить логотип канала, используйте storeChannelLogo().
удалять канал;
Kotlin
context.contentResolver.delete(TvContractCompat.buildChannelUri(channelId), null, null)
Java
context.getContentResolver().delete(TvContractCompat.buildChannelUri(channelId), null, null);
Программы
Программы – это отдельные карточки контента, которые показываются на канале. Вы можете публиковать программы как в пользовательских каналах приложения, так и в системном канале "Смотреть дальше".
Как добавить программы в канал приложения
Создайте объект PreviewProgram.Builder и задайте его атрибуты:
Kotlin
val builder = PreviewProgram.Builder()
builder.setChannelId(channelId)
.setType(TvContractCompat.PreviewPrograms.TYPE_CLIP)
.setTitle("Title")
.setDescription("Program description")
.setPosterArtUri(uri)
.setIntentUri(uri)
.setInternalProviderId(appProgramId)
Java
PreviewProgram.Builder builder = new PreviewProgram.Builder();
builder.setChannelId(channelId)
.setType(TvContractCompat.PreviewPrograms.TYPE_CLIP)
.setTitle("Title")
.setDescription("Program description")
.setPosterArtUri(uri)
.setIntentUri(uri)
.setInternalProviderId(appProgramId);
Добавьте дополнительные атрибуты в зависимости от типа программы. (Чтобы посмотреть атрибуты, доступные для каждого типа программы, ознакомьтесь с таблицами ниже.)
Вставьте программу в поставщика:
Kotlin
var programUri = context.contentResolver.insert(TvContractCompat.PreviewPrograms.CONTENT_URI,
builder.build().toContentValues())
Java
Uri programUri = context.getContentResolver().insert(TvContractCompat.PreviewPrograms.CONTENT_URI,
builder.build().toContentValues());
Получите идентификатор программы, чтобы использовать его в дальнейшем:
Kotlin
val programId = ContentUris.parseId(programUri)
Java
long programId = ContentUris.parseId(programUri);
Как добавлять программы на канал "Смотреть дальше"
Чтобы добавить программы в канал "Смотреть дальше", ознакомьтесь с разделом Добавление программ в канал "Смотреть дальше".
Как обновить программу
Вы можете изменить информацию о программе. Например, вы можете обновить цену проката фильма или индикатор выполнения, показывающий, какую часть программы пользователь уже посмотрел.
Используйте PreviewProgram.Builder, чтобы задать атрибуты, которые нужно изменить, а затем вызовите getContentResolver().update, чтобы обновить программу. Укажите идентификатор программы, который вы сохранили при ее добавлении:
Kotlin
context.contentResolver.update(
TvContractCompat.buildPreviewProgramUri(programId),
builder.build().toContentValues(), null, null
)
Java
context.getContentResolver().update(TvContractCompat.buildPreviewProgramUri(programId),
builder.build().toContentValues(), null, null);
Как удалить программу
Kotlin
context.contentResolver
.delete(TvContractCompat.buildPreviewProgramUri(programId), null, null)
Java
context.getContentResolver().delete(TvContractCompat.buildPreviewProgramUri(programId), null, null);
Обработка действий пользователя
Вы можете добавить в приложение интерфейс, который позволит пользователям находить и добавлять каналы. Приложение также должно обрабатывать взаимодействия с каналами после их появления на главном экране.
Поиск и добавление каналов
В приложении можно добавить элемент интерфейса, позволяющий пользователю выбрать и добавить каналы (например, кнопку с предложением добавить канал).
После того как пользователь запросит определенный канал, выполните этот код, чтобы получить разрешение пользователя на добавление канала в интерфейс главного экрана:
Kotlin
val intent = Intent(TvContractCompat.ACTION_REQUEST_CHANNEL_BROWSABLE)
intent.putExtra(TvContractCompat.EXTRA_CHANNEL_ID, channelId)
try {
activity.startActivityForResult(intent, 0)
} catch (e: ActivityNotFoundException) {
// handle error
}
Java
Intent intent = new Intent(TvContractCompat.ACTION_REQUEST_CHANNEL_BROWSABLE);
intent.putExtra(TvContractCompat.EXTRA_CHANNEL_ID, channelId);
try {
activity.startActivityForResult(intent, 0);
} catch (ActivityNotFoundException e) {
// handle error
}
Появится диалоговое окно с запросом на одобрение канала. Обработайте результат запроса в методе onActivityResult своего объекта activity (Activity.RESULT_CANCELED или Activity.RESULT_OK).
События на главном экране Android TV
Когда пользователь взаимодействует с программами и каналами, опубликованными приложением, главный экран отправляет приложению намерения:
- Когда пользователь нажимает на логотип канала, главный экран отправляет в приложение значение
Uri, сохраненное в атрибуте APP_LINK_INTENT_URI канала. Приложение должно просто запустить свой основной пользовательский интерфейс или представление, связанное с выбранным каналом. - Когда пользователь выбирает программу, главный экран отправляет в приложение значение
Uri, сохраненное в атрибуте INTENT_URI программы. Приложение должно воспроизвести выбранный контент. - Пользователь может указать, что его больше не интересует программа и он хочет удалить ее с главного экрана. Система удаляет программу из интерфейса и отправляет приложению, которому принадлежит программа, намерение (android.media.tv.ACTION_PREVIEW_PROGRAM_BROWSABLE_DISABLED или android.media.tv.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED) с идентификатором программы. Приложение должно удалить программу из поставщика и НЕ добавлять ее повторно.
Убедитесь, что вы создали фильтры интентов для всех Uris, которые главный экран отправляет для взаимодействия с пользователем. Например:
<receiver
android:name=".WatchNextProgramRemoved"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.media.tv.ACTION_WATCH_NEXT_PROGRAM_BROWSABLE_DISABLED" />
</intent-filter>
</receiver>
Дополнительные сведения
- Для работы со многими ТВ-приложениями требуется вход в аккаунт. В этом случае
BroadcastReceiver, который ожидаетandroid.media.tv.action.INITIALIZE_PROGRAMS, должен предлагать контент канала для неаутентифицированных пользователей. Например, в приложении можно сначала показывать лучший или популярный контент. После входа в аккаунт пользователю может показываться персонализированный контент. Это отличная возможность для приложений продавать пользователям дополнительные услуги до того, как они войдут в систему. - Если приложение неактивно и вам нужно обновить канал или программу, используйте
JobScheduler, чтобы запланировать работу (см.JobSchedulerиJobService). - Система может отозвать разрешения поставщика, если приложение работает некорректно (например, постоянно отправляет поставщику спам). Обязательно оберните код, который обращается к поставщику, в блоки try-catch, чтобы обрабатывать исключения безопасности.
Перед обновлением программ и каналов запросите у поставщика данные, которые необходимо обновить, и сверьте их. Например, не нужно обновлять программу, которую пользователь хочет удалить из интерфейса. Используйте фоновое задание, которое вставляет или обновляет данные в поставщике после запроса существующих данных, а затем запрашивает одобрение для ваших каналов. Вы можете запускать это задание при запуске приложения и всякий раз, когда приложению необходимо обновить свои данные.
Kotlin
context.contentResolver
.query(
TvContractCompat.buildChannelUri(channelId),
null, null, null, null).use({
cursor-> if (cursor != null and cursor.moveToNext()) {
val channel = Channel.fromCursor(cursor)
if (channel.isBrowsable()) {
//update channel's programs
}
}
})
Java
try (Cursor cursor = context.getContentResolver()
.query(
TvContractCompat.buildChannelUri(channelId),
null,
null,
null,
null)) {
if (cursor != null && cursor.moveToNext()) {
Channel channel = Channel.fromCursor(cursor);
if (channel.isBrowsable()) {
//update channel's programs
}
}
}
Используйте уникальные URI для всех изображений (логотипов, значков, изображений контента). При обновлении изображения обязательно используйте другой URI. Все изображения кешируются. Если вы не измените URI при изменении изображения, будет по-прежнему показываться старое изображение.
Помните, что операторы WHERE не разрешены, и вызовы поставщиков с операторами WHERE вызовут исключение безопасности.
Атрибуты
В этом разделе атрибуты каналов и программ описаны отдельно.
Атрибуты канала
Для каждого канала необходимо указать следующие атрибуты:
| Атрибут | Примечания |
|---|---|
| ПЕЧАТ | задано значение TYPE_PREVIEW. |
| DISPLAY_NAME | имеет значение, равное названию канала. |
| APP_LINK_INTENT_URI | Когда пользователь выбирает логотип канала, система отправляет намерение начать действие, которое представляет контент, относящийся к каналу. Укажите в этом атрибуте URI, который используется в фильтре интентов для этого объекта Activity. |
Кроме того, в канале есть шесть полей, зарезервированных для внутреннего использования приложения. Эти поля можно использовать для хранения ключей или других значений, которые помогают приложению сопоставить канал со своей внутренней структурой данных:
- INTERNAL_PROVIDER_ID
- INTERNAL_PROVIDER_DATA
- INTERNAL_PROVIDER_FLAG1
- INTERNAL_PROVIDER_FLAG2
- INTERNAL_PROVIDER_FLAG3
- INTERNAL_PROVIDER_FLAG4
Атрибуты программы
Подробную информацию об атрибутах для каждого типа программ можно найти на следующих страницах:
Пример кода
Чтобы узнать больше о создании приложений, взаимодействующих с главным экраном, и добавлении каналов и программ на главный экран Android TV, ознакомьтесь с практической работой.