Um serviço de entrada de TV representa uma fonte de stream de mídia e permite apresentar seu conteúdo de mídia em um de TV com transmissão linear, como canais e programas. Com um serviço de entrada para TV, é possível fornecer controle dos pais, informações sobre o guia da programação e classificações do conteúdo. O serviço de entrada de TV funciona com o app de TV do sistema Android. Este aplicativo controla e apresenta o conteúdo do canal na TV. O app de TV do sistema foi desenvolvido especificamente para dispositivos e não pode ser modificado por apps de terceiros. Para mais informações sobre o TV Input Framework (TIF) e os componentes dela, consulte TV Input Framework (link em inglês).
Criar um serviço de entrada de TV usando a TIF Companion Library
A TIF Companion Library é um framework que oferece implementações de recursos comuns do serviço de entrada de TV. Ele foi feito para ser usado por OEMs na criação Canais somente para Android 5.0 (API de nível 21) ao Android 7.1 (API de nível 25).
Atualizar seu projeto
A TIF Companion Library está disponível para uso legado por OEMs no androidtv-sample-inputs (em inglês) repositório de dados. Consulte esse repositório para conferir um exemplo de como incluir a biblioteca em um app.
Declarar seu serviço de entrada de TV no manifesto
Seu app precisa fornecer um endereço de e-mail compatível com TvInputService
serviço que o sistema usa para acessar seu aplicativo. TIF
A biblioteca complementar oferece a classe BaseTvInputService
, que
fornece uma implementação padrão de TvInputService
que você pode personalizar. Crie uma subclasse de BaseTvInputService
.
e declarar a subclasse no manifesto como um serviço.
Na declaração do manifesto, especifique
BIND_TV_INPUT
para permitir que o
para conectar a entrada da TV ao sistema. Um serviço do sistema
executa a vinculação
BIND_TV_INPUT
.
O app de TV do sistema envia solicitações aos serviços de entrada de TV
pela interface TvInputManager
.
Na declaração do serviço, inclua um filtro de intent que especifique
TvInputService
como a ação a ser realizada com o
intenção. Além disso, declare os metadados de serviço com um recurso XML separado. A
declaração de serviço, filtro de intent e declaração de metadados de serviço são mostrados
no exemplo a seguir:
<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>
Defina os metadados de serviço em um arquivo XML separado. O serviço O arquivo XML de metadados deve incluir uma interface de configuração que descreva a entrada da TV configuração inicial e busca de canais. O arquivo de metadados também deve conter um que indica se os usuários podem ou não gravar o conteúdo. Para mais informações sobre como oferecer suporte à gravação de conteúdo no seu app, consulte Suporte à gravação de conteúdo.
O arquivo de metadados de serviço está localizado no diretório de recursos XML.
para seu app e precisa corresponder ao nome do recurso declarado na
manifesto do aplicativo. Usando as entradas de manifesto do exemplo anterior, você usaria
crie o arquivo XML em res/xml/richtvinputservice.xml
, com o
o seguinte conteúdo:
<?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" />
Definir canais e criar atividades de configuração
Seu serviço de entrada de TV precisa definir pelo menos um canal que os usuários pelo app de TV do sistema. Você deve registrar seus canais no banco de dados do sistema e fornecem uma atividade de configuração invoca quando não encontra um canal para seu app.
Primeiro, permita que seu app leia e grave no sistema Guia de programação (EPG), cujos dados incluem canais e programas disponíveis para o usuário. Para permitir que seu aplicativo realize essas ações e sincronize com o EPG após a reinicialização do dispositivo, adicione os seguintes elementos ao manifesto do app:
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED "/>
Adicione o seguinte elemento para garantir que seu aplicativo apareça na Google Play Store como um app que oferece canais de conteúdo no Android TV:
<uses-feature android:name="android.software.live_tv" android:required="true" />
Em seguida, crie uma classe que estenda o EpgSyncJobService
. Essa classe abstrata facilita a criação de um serviço de vagas que
Cria e atualiza canais no banco de dados do sistema.
Na subclasse, crie e retorne sua lista completa de canais em
getChannels()
: Se os canais vêm de um arquivo XMLTV,
use a classe XmlTvParser
. Caso contrário, gere
canais de forma programática usando a classe Channel.Builder
.
Para cada canal, o sistema chama getProgramsForChannel()
.
quando precisa de uma lista de programas que podem ser visualizados em uma determinada janela de tempo.
no canal. Retorne uma lista de objetos Program
para o
canal. Use a classe XmlTvParser
para acessar programas de uma
XMLTV ou gerá-los de forma programática usando a
Program.Builder
.
Para cada objeto Program
, use uma
Objeto InternalProviderData
para definir informações do programa, como o
tipo de vídeo do programa. Se você tem um número limitado de programas
quiser que o canal se repita em loop, use o
Método InternalProviderData.setRepeatable()
com um valor de
true
ao definir informações sobre o programa.
Depois de implementar o serviço de tarefas, adicione-o ao manifesto do seu app:
<service android:name=".sync.SampleJobService" android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true" />
Para terminar, crie uma atividade de configuração. Sua atividade de configuração deve fornecer uma maneira para sincronizar dados de canais e programas. Uma maneira de fazer isso é que o usuário faça isso por meio da interface na atividade. O app também pode fazer isso automaticamente quando a atividade iniciar. Quando a atividade de configuração precisar sincronizar os canais e informações do programa, o app deve iniciar o serviço de tarefas:
Kotlin
val inputId = getActivity().intent.getStringExtra(TvInputInfo.EXTRA_INPUT_ID) EpgSyncJobService.cancelAllSyncRequests(getActivity()) EpgSyncJobService.requestImmediateSync( getActivity(), inputId, ComponentName(getActivity(), SampleJobService::class.java) )
Java
String inputId = getActivity().getIntent().getStringExtra(TvInputInfo.EXTRA_INPUT_ID); EpgSyncJobService.cancelAllSyncRequests(getActivity()); EpgSyncJobService.requestImmediateSync(getActivity(), inputId, new ComponentName(getActivity(), SampleJobService.class));
Usar o método requestImmediateSync()
para sincronizar
serviço de trabalho. Como o usuário precisa aguardar o término da sincronização, você deve
manter o período de solicitação relativamente curto.
Use o método setUpPeriodicSync()
para que o serviço de jobs
sincronize periodicamente os dados dos canais e dos programas em segundo plano:
Kotlin
EpgSyncJobService.setUpPeriodicSync( context, inputId, ComponentName(context, SampleJobService::class.java) )
Java
EpgSyncJobService.setUpPeriodicSync(context, inputId, new ComponentName(context, SampleJobService.class));
A TIF Companion Library fornece um método adicional sobrecarregado de
requestImmediateSync()
, que permite especificar a duração
dados de canais sejam sincronizados em milissegundos. O método padrão sincroniza
em dados de canais.
A TIF Companion Library também fornece um método adicional sobrecarregado de
setUpPeriodicSync()
, que permite especificar a duração
dados de canais a serem sincronizados e com que frequência a sincronização periódica deve ocorrer. A
O método padrão sincroniza 48 horas de dados de canais a cada 12 horas.
Para mais detalhes sobre dados de canais e o EPG, consulte Trabalhar com dados de canais.
Processar solicitações de sintonização e reprodução de mídia
Quando um usuário seleciona um canal específico, o app de TV do sistema usa uma
Session
, criado pelo seu app, para sintonizar o canal solicitado
e reproduzir conteúdo. A TIF Companion Library oferece vários
que podem ser estendidas para lidar com chamadas de canal e sessão do sistema.
A subclasse BaseTvInputService
cria sessões que processam
solicitações de ajuste. Substitua o
onCreateSession()
, crie uma sessão estendida de
a classe BaseTvInputService.Session
e chame
super.sessionCreated()
pela nova sessão. Nos seguintes
exemplo, onCreateSession()
retorna um
Objeto RichTvInputSessionImpl
que estende
BaseTvInputService.Session
:
Kotlin
override fun onCreateSession(inputId: String): Session = RichTvInputSessionImpl(this, inputId).apply { setOverlayViewEnabled(true) }
Java
@Override public final Session onCreateSession(String inputId) { RichTvInputSessionImpl session = new RichTvInputSessionImpl(this, inputId); session.setOverlayViewEnabled(true); return session; }
Quando o usuário usa o app de TV do sistema para começar a visualizar um dos seus canais,
o sistema chamará o método onPlayChannel()
da sessão. Substituir
este método se for necessário fazer qualquer inicialização de canal especial antes que o
começar a reproduzir.
O sistema recebe o programa que está agendado e chama seu
método onPlayProgram()
da sessão, especificando o programa
e o horário de início em milissegundos. Use o
TvPlayer
para começar a jogar o programa.
O código do seu player de mídia precisa implementar TvPlayer
para processar
eventos de reprodução específicos. A classe TvPlayer
processa recursos
como controles de time-shifting sem aumentar a complexidade
BaseTvInputService
.
No método getTvPlayer()
da sua sessão, retorne
seu player de mídia que implemente TvPlayer
. A
O app de exemplo Serviço de entrada de TV implementa um player de mídia que usa
ExoPlayer (links em inglês).
Criar um serviço de entrada de TV usando o framework de entrada de TV
Se seu serviço de entrada de TV não puder usar a TIF Companion Library, você precisará para implementar os seguintes componentes:
- O
TvInputService
oferece disponibilidade de longa duração e em segundo plano para a entrada da TV - O
TvInputService.Session
mantém o estado da entrada de TV e se comunica com o app de hospedagem TvContract
descreve os canais e programas disponíveis para a TV entradaTvContract.Channels
representa informações sobre um canal de TV.TvContract.Programs
descreve um programa de TV com dados como programa título e horário de inícioTvTrackInfo
representa uma faixa de áudio, vídeo ou legendas.TvContentRating
descreve uma classificação do conteúdo e permite conteúdo personalizado esquemas de classificaçãoTvInputManager
fornece uma API para o app de TV do sistema e gerencia a interação com entradas e apps de TV
Você também precisa fazer o seguinte:
- Declare o serviço de entrada de TV no manifesto como descrito em Declarar seu serviço de entrada de TV no manifesto do app.
- Crie o arquivo de metadados do serviço.
- Crie e registre suas informações de canais e programas.
- Crie suas atividades de configuração.
Definir o serviço de entrada de TV
Estenda a classe TvInputService
para seu serviço. Um
A implementação de TvInputService
é uma
serviço vinculado em que o serviço do sistema
é o cliente que é vinculado a ela. Os métodos do ciclo de vida do serviço
que precisam ser implementados estão ilustrados na figura 1.
O método onCreate()
inicializa e inicia a
HandlerThread
, que fornece uma linha de execução de processo separada da linha de execução de IU para
e lidar com ações do sistema. No exemplo abaixo, o onCreate()
inicializa o CaptioningManager
e se prepara para processar
a ACTION_BLOCKED_RATINGS_CHANGED
e ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED
. Esses
as ações descrevem intents do sistema disparadas quando o usuário altera as configurações de controle dos pais e quando
houver uma mudança na lista de classificações bloqueadas.
Kotlin
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) }
Java
@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); }
![](https://developer.android.com/static/images/tv/tvinput-life.png?authuser=19&hl=pt)
Figura 1. Ciclo de vida da classe TvInputService.
Consulte
Controle de conteúdo para saber mais sobre como trabalhar com conteúdo bloqueado e fornecer
o controle da família. Acesse TvInputManager
para conferir mais ações do sistema que
que você queira processar no serviço de entrada de TV.
O TvInputService
cria um
TvInputService.Session
que implementa Handler.Callback
para lidar com alterações no estado do player. Com
onSetSurface()
,
o TvInputService.Session
define a Surface
com o
conteúdo em vídeo. Consulte Integrar o player à plataforma
para mais informações sobre como trabalhar com Surface
para renderizar vídeos.
O TvInputService.Session
processa
onTune()
quando o usuário seleciona um canal e notifica o aplicativo de TV do sistema sobre alterações no conteúdo e
metadados de conteúdo. Esses métodos notify()
são descritos em
"Controlar conteúdo" e Gerenciar a seleção de músicas
mais adiante neste treinamento.
Definir atividades de configuração
O app de TV do sistema trabalha com as atividades de configuração definidas para sua entrada de TV. A a atividade de configuração é necessária e deve fornecer pelo menos um registro de canal para o banco de dados do sistema. A o app de TV do sistema invoca a atividade de configuração quando não encontra um canal para a entrada da TV.
A atividade de configuração descreve para o app de TV do sistema os canais disponibilizados pela TV entrada, como demonstrado na próxima lição, Criar e atualizar os dados do canal.
Outras referências
- android.media.tv (link em inglês)
- TV Framework de entrada