Служба ТВ-входа представляет собой источник медиапотока и позволяет вам представлять медиаконтент в линейной, широковещательной телевизионной форме в виде каналов и программ. С помощью услуги ТВ-входа вы можете обеспечить родительский контроль, информацию о программе передач и рейтинги контента. Служба ТВ-входа работает с системным приложением Android TV. Это приложение в конечном итоге контролирует и отображает контент канала на телевизоре. Приложение системного ТВ разработано специально для устройства и недоступно для сторонних приложений. Дополнительные сведения об архитектуре TV Input Framework (TIF) и ее компонентах см. в разделе TV Input Framework .
Создайте службу телевизионного ввода с помощью сопутствующей библиотеки TIF.
Сопутствующая библиотека TIF — это платформа, которая обеспечивает расширяемую реализацию общих функций службы телевизионного ввода. Он предназначен для использования OEM-производителями для создания каналов только для Android 5.0 (уровень API 21) по Android 7.1 (уровень API 25).
Обновите свой проект
Сопутствующая библиотека TIF доступна для устаревшего использования OEM-производителями в репозитории androidtv-sample-inputs . См. этот репозиторий, где приведен пример включения библиотеки в приложение.
Объявите службу ТВ-ввода в манифесте.
Ваше приложение должно предоставлять службу, совместимую с TvInputService
, которую система использует для доступа к вашему приложению. Сопутствующая библиотека TIF предоставляет класс BaseTvInputService
, который предоставляет реализацию TvInputService
по умолчанию, которую вы можете настроить. Создайте подкласс BaseTvInputService
и объявите подкласс в своем манифесте как службу.
В объявлении манифеста укажите разрешение BIND_TV_INPUT
, чтобы разрешить службе подключать вход ТВ к системе. Системная служба выполняет привязку и имеет разрешение BIND_TV_INPUT
. Системное ТВ-приложение отправляет запросы к службам ТВ-ввода через интерфейс TvInputManager
.
В декларацию службы включите фильтр намерений, который указывает TvInputService
в качестве действия, которое необходимо выполнить с намерением. Также объявите метаданные службы как отдельный ресурс XML. Объявление службы, фильтр намерений и объявление метаданных службы показаны в следующем примере:
<service android:name=".rich.RichTvInputService" android:label="@string/rich_input_label" android:permission="android.permission.BIND_TV_INPUT"> <!-- Required filter used by the system to launch our account service. --> <intent-filter> <action android:name="android.media.tv.TvInputService" /> </intent-filter> <!-- An XML file which describes this input. This provides pointers to the RichTvInputSetupActivity to the system/TV app. --> <meta-data android:name="android.media.tv.input" android:resource="@xml/richtvinputservice" /> </service>
Определите метаданные службы в отдельном XML-файле. XML-файл метаданных службы должен включать интерфейс настройки, описывающий первоначальную конфигурацию телевизионного входа и сканирование каналов. Файл метаданных также должен содержать флаг, указывающий, могут ли пользователи записывать контент. Дополнительные сведения о поддержке записи контента в вашем приложении см. в разделе Поддержка записи контента .
Файл метаданных службы находится в каталоге ресурсов XML вашего приложения и должен соответствовать имени ресурса, объявленного вами в манифесте. Используя записи манифеста из предыдущего примера, вы создадите XML-файл по адресу res/xml/richtvinputservice.xml
со следующим содержимым:
<?xml version="1.0" encoding="utf-8"?> <tv-input xmlns:android="http://schemas.android.com/apk/res/android" android:canRecord="true" android:setupActivity="com.example.android.sampletvinput.rich.RichTvInputSetupActivity" />
Определите каналы и создайте свою настройку
Ваша служба ТВ-входа должна определить хотя бы один канал, к которому пользователи получают доступ через системное ТВ-приложение. Вам следует зарегистрировать свои каналы в системной базе данных и предоставить действие по настройке, которое система вызывает, когда не может найти канал для вашего приложения.
Сначала разрешите вашему приложению читать и записывать в системный электронный программный гид (EPG), данные которого включают каналы и программы, доступные пользователю. Чтобы приложение могло выполнять эти действия и синхронизироваться с EPG после перезагрузки устройства, добавьте в манифест приложения следующие элементы:
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED "/>
Добавьте следующий элемент, чтобы ваше приложение отображалось в Google Play Store как приложение, предоставляющее каналы контента на Android TV:
<uses-feature android:name="android.software.live_tv" android:required="true" />
Затем создайте класс, расширяющий класс EpgSyncJobService
. Этот абстрактный класс упрощает создание службы заданий, которая создает и обновляет каналы в системной базе данных.
В своем подклассе создайте и верните полный список каналов в getChannels()
. Если ваши каналы взяты из файла XMLTV, используйте класс XmlTvParser
. В противном случае сгенерируйте каналы программно с помощью класса Channel.Builder
.
Для каждого канала система вызывает getProgramsForChannel()
когда ей нужен список программ, которые можно просмотреть в течение заданного временного окна на канале. Возвращает список объектов Program
для канала. Используйте класс XmlTvParser
для получения программ из файла XMLTV или создайте их программным способом с помощью класса Program.Builder
.
Для каждого объекта Program
используйте объект InternalProviderData
, чтобы задать информацию о программе, например тип видео программы. Если у вас есть только ограниченное количество программ, которые вы хотите, чтобы канал повторял в цикле, используйте метод InternalProviderData.setRepeatable()
со значением true
при настройке информации о вашей программе.
После реализации службы заданий добавьте ее в манифест вашего приложения:
<service android:name=".sync.SampleJobService" android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true" />
Наконец, создайте действие настройки. Действия по настройке должны обеспечивать возможность синхронизации данных канала и программы. Один из способов сделать это — предоставить пользователю возможность сделать это через пользовательский интерфейс в действии. Вы также можете настроить приложение на автоматическое выполнение этого действия при запуске активности. Когда в процессе настройки необходимо синхронизировать информацию о канале и программе, приложение должно запустить службу заданий:
Котлин
val inputId = getActivity().intent.getStringExtra(TvInputInfo.EXTRA_INPUT_ID) EpgSyncJobService.cancelAllSyncRequests(getActivity()) EpgSyncJobService.requestImmediateSync( getActivity(), inputId, ComponentName(getActivity(), SampleJobService::class.java) )
Ява
String inputId = getActivity().getIntent().getStringExtra(TvInputInfo.EXTRA_INPUT_ID); EpgSyncJobService.cancelAllSyncRequests(getActivity()); EpgSyncJobService.requestImmediateSync(getActivity(), inputId, new ComponentName(getActivity(), SampleJobService.class));
Используйте метод requestImmediateSync()
для синхронизации службы заданий. Пользователь должен дождаться завершения синхронизации, поэтому период запроса должен быть относительно коротким.
Используйте метод setUpPeriodicSync()
, чтобы служба заданий периодически синхронизировала данные канала и программы в фоновом режиме:
Котлин
EpgSyncJobService.setUpPeriodicSync( context, inputId, ComponentName(context, SampleJobService::class.java) )
Ява
EpgSyncJobService.setUpPeriodicSync(context, inputId, new ComponentName(context, SampleJobService.class));
Сопутствующая библиотека TIF предоставляет дополнительный перегруженный метод requestImmediateSync()
, который позволяет указать продолжительность синхронизации данных канала в миллисекундах. Метод по умолчанию синхронизирует данные канала за один час.
Сопутствующая библиотека TIF также предоставляет дополнительный перегруженный метод setUpPeriodicSync()
, который позволяет указать продолжительность синхронизации данных канала и частоту периодической синхронизации. Метод по умолчанию синхронизирует 48 часов данных канала каждые 12 часов.
Дополнительные сведения о данных канала и EPG см. в разделе Работа с данными канала .
Обработка запросов на настройку и воспроизведение мультимедиа
Когда пользователь выбирает определенный канал, системное ТВ-приложение использует Session
, созданный вашим приложением, для настройки на запрошенный канал и воспроизведения контента. Сопутствующая библиотека TIF предоставляет несколько классов, которые можно расширить для обработки вызовов каналов и сеансов из системы.
Ваш подкласс BaseTvInputService
создает сеансы, которые обрабатывают запросы настройки. Переопределите метод onCreateSession()
, создайте сеанс, расширенный из класса BaseTvInputService.Session
, и вызовите super.sessionCreated()
с новым сеансом. В следующем примере onCreateSession()
возвращает объект RichTvInputSessionImpl
, который расширяет BaseTvInputService.Session
:
Котлин
override fun onCreateSession(inputId: String): Session = RichTvInputSessionImpl(this, inputId).apply { setOverlayViewEnabled(true) }
Ява
@Override public final Session onCreateSession(String inputId) { RichTvInputSessionImpl session = new RichTvInputSessionImpl(this, inputId); session.setOverlayViewEnabled(true); return session; }
Когда пользователь использует системное ТВ-приложение, чтобы начать просмотр одного из ваших каналов, система вызывает метод onPlayChannel()
вашего сеанса. Переопределите этот метод, если вам нужно выполнить какую-либо специальную инициализацию канала перед началом воспроизведения программы.
Затем система получает запланированную на данный момент программу и вызывает метод onPlayProgram()
вашего сеанса, указывая информацию о программе и время начала в миллисекундах. Используйте интерфейс TvPlayer
, чтобы начать воспроизведение программы.
Код вашего медиаплеера должен реализовывать TvPlayer
для обработки определенных событий воспроизведения. Класс TvPlayer
обрабатывает такие функции, как элементы управления сдвигом во времени, не усложняя реализацию BaseTvInputService
.
В методе getTvPlayer()
вашего сеанса верните медиаплеер, реализующий TvPlayer
. Пример приложения TV Input Service реализует медиаплеер, использующий ExoPlayer .
Создайте службу ТВ-ввода, используя структуру ТВ-ввода.
Если ваша служба телевизионного ввода не может использовать сопутствующую библиотеку TIF, вам необходимо реализовать следующие компоненты:
-
TvInputService
обеспечивает длительную и фоновую доступность телевизионного входа. -
TvInputService.Session
поддерживает состояние входа телевизора и взаимодействует с приложением хостинга. -
TvContract
описывает каналы и программы, доступные на входе телевизора. -
TvContract.Channels
представляет информацию о телеканале. -
TvContract.Programs
описывает телепрограмму с такими данными, как название программы и время начала. -
TvTrackInfo
представляет собой дорожку аудио, видео или субтитров. -
TvContentRating
описывает рейтинг контента и позволяет использовать собственные схемы рейтинга контента. -
TvInputManager
предоставляет API для системного ТВ-приложения и управляет взаимодействием с ТВ-входами и приложениями.
Вам также необходимо сделать следующее:
- Объявите службу телевизионного ввода в манифесте, как описано в разделе «Объявление службы телевизионного ввода в манифесте» .
- Создайте файл метаданных службы.
- Создайте и зарегистрируйте свой канал и информацию о программе.
- Создайте действие по настройке.
Определите службу телевизионного входа
Для вашего сервиса вы расширяете класс TvInputService
. Реализация TvInputService
— это привязанная служба , где системная служба — это клиент, который привязывается к ней. Методы жизненного цикла сервиса, которые вам необходимо реализовать, показаны на рисунке 1.
Метод onCreate()
инициализирует и запускает HandlerThread
, который предоставляет поток процесса, отдельный от потока пользовательского интерфейса, для обработки действий, управляемых системой. В следующем примере метод onCreate()
инициализирует CaptioningManager
и готовится к обработке действий ACTION_BLOCKED_RATINGS_CHANGED
и ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED
. Эти действия описывают намерения системы, которые активируются, когда пользователь меняет настройки родительского контроля и когда происходит изменение в списке заблокированных оценок.
Котлин
override fun onCreate() { super.onCreate() handlerThread = HandlerThread(javaClass.simpleName).apply { start() } dbHandler = Handler(handlerThread.looper) handler = Handler() captioningManager = getSystemService(Context.CAPTIONING_SERVICE) as CaptioningManager setTheme(android.R.style.Theme_Holo_Light_NoActionBar) sessions = mutableListOf<BaseTvInputSessionImpl>() val intentFilter = IntentFilter().apply { addAction(TvInputManager.ACTION_BLOCKED_RATINGS_CHANGED) addAction(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED) } registerReceiver(broadcastReceiver, intentFilter) }
Ява
@Override public void onCreate() { super.onCreate(); handlerThread = new HandlerThread(getClass() .getSimpleName()); handlerThread.start(); dbHandler = new Handler(handlerThread.getLooper()); handler = new Handler(); captioningManager = (CaptioningManager) getSystemService(Context.CAPTIONING_SERVICE); setTheme(android.R.style.Theme_Holo_Light_NoActionBar); sessions = new ArrayList<BaseTvInputSessionImpl>(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(TvInputManager .ACTION_BLOCKED_RATINGS_CHANGED); intentFilter.addAction(TvInputManager .ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED); registerReceiver(broadcastReceiver, intentFilter); }
Дополнительные сведения о работе с заблокированным содержимым и обеспечении родительского контроля см. в разделе «Контроль над содержимым». См. TvInputManager
для получения дополнительных системных действий, которые вы, возможно, захотите обрабатывать в своей службе ТВ-ввода.
TvInputService
создает TvInputService.Session
, который реализует Handler.Callback
для обработки изменений состояния игрока. С помощью onSetSurface()
TvInputService.Session
устанавливает Surface
с видеоконтентом. Дополнительные сведения о работе с Surface
для рендеринга видео см. в разделе Интеграция проигрывателя с Surface .
TvInputService.Session
обрабатывает событие onTune()
, когда пользователь выбирает канал, и уведомляет системное ТВ-приложение об изменениях в контенте и метаданных контента. Эти методы notify()
описаны в разделах «Управление содержимым и управление выбором дорожки» далее в этом обучении.
Определите действия по настройке
Системное ТВ-приложение работает с действиями по настройке, которые вы определяете для своего ТВ-входа. Действие настройки является обязательным и должно предоставить хотя бы одну запись канала для системной базы данных. Системное ТВ-приложение запускает операцию настройки, когда не может найти канал для ТВ-входа.
Действие настройки описывает системному ТВ-приложению каналы, доступные через вход телевизора, как показано в следующем уроке « Создание и обновление данных канала» .