1. Introdução
Assistir a seguir
O canal "Assistir a seguir" é a linha que aparece na tela inicial do Android TV com sugestões de vídeos para os usuários. Dependendo da versão do sistema, a linha "Assistir a seguir" pode se chamar Assistir em seguida ou Continuar assistindo.
O sistema cria e mantém esse canal. Cada item desse canal é chamado de programa. O app pode adicionar, atualizar ou remover programas do canal "Assistir a seguir", como conteúdos que o usuário deixou de assistir no meio ou com que o usuário interagiu, por exemplo, o próximo episódio de uma série ou a próxima temporada de um programa.
Conceitos
O canal "Assistir a seguir" permite que seu app gere um novo engajamento com o usuário.
É possível adicionar, atualizar ou remover conteúdos do canal "Assistir a seguir" com que o usuário já tenha interagido. O app pode sugerir um vídeo não concluído ou um próximo episódio, uma próxima série, entre outros.
Ele também pode remover o episódio depois de assistido e adicionar o episódio seguinte da nova temporada de uma série.
Existem quatro tipos de casos de uso para o canal "Assistir a seguir":
- Continuar assistindo a um vídeo que o usuário não terminou.
- Sugerir o próximo vídeo para o usuário assistir. Por exemplo, se o usuário tiver terminado de assistir o episódio 1, você poderá sugerir o episódio 2.
- Mostrar novos episódios de uma série que o usuário estava assistindo.
- Manter uma lista de interesses de vídeos adicionados pelo usuário.
Este codelab mostra como incluir um vídeo que o usuário pausou no canal "Assistir a seguir". Ele também aborda como remover um vídeo desse canal depois que ele é reproduzido até o final e como adicionar o próximo episódio, quando disponível.
Este codelab não abrange os casos de uso do canal "Assistir a seguir" para novos lançamentos de episódios e para a lista de interesses.
"Assistir a seguir" para filmes e programas de TV
O canal "Assistir a seguir" é um recurso muito importante da tela inicial do Android TV, porque ajuda o usuário a retomar filmes e programas de TV não concluídos. Ele é especialmente importante para usuários que assistem a programas de TV, já que uma série geralmente tem muitos episódios e muitas vezes o usuário continuará assistindo do ponto em que parou.
Imagine o momento em que o usuário volta ao app e fica em frente à TV decidindo o que assistir. Com o "Assistir a seguir", o app permite que ele retome programas de TV a partir do ponto em que parou diretamente na tela inicial. Isso aumenta o engajamento do usuário, o que beneficia seu app e o usuário.
Este codelab vai ajudar você a usar o app de TV de referência, mostrar como abordar diferentes casos do canal "Assistir a seguir" e explicar as diretrizes de qualidade do Google para esse recurso. O objetivo deste codelab é tratar especificamente de programas de TV, mas você pode aplicar regras semelhantes para filmes.
Disponibilidade
O código deste codelab funciona em dispositivos Android TV, incluindo os que executam a experiência do Google TV.
O que você vai criar
Neste codelab, você vai adicionar, remover e atualizar o canal "Assistir a seguir" para filmes e programas de TV. Esse app vai:
- implementar diferentes casos de uso para processar filmes;
- implementar diferentes casos de uso para processar programas de TV.
O que você vai aprender
- Diretrizes de qualidade do Google para o canal "Assistir a seguir"
O que é necessário
- Conhecimento básico de desenvolvimento de apps Android.
- Android Studio 4.1 ou versão mais recente. Faça o download aqui.
2. Etapas da configuração
Clonar o projeto inicial
Você pode fazer o download do código-fonte no repositório do GitHub:
git clone https://github.com/android/codelab-watchnext-for-movie-tv-episodes.git
Ou faça o download diretamente usando o link abaixo.
Abra o Android Studio e clique em File > Open na barra de menus ou em Open an Existing Android Studio Project na tela inicial e selecione a pasta que você acabou de clonar.
Noções básicas sobre o projeto inicial
Há quatro etapas no projeto. Em cada etapa, você vai adicionar um código com base nas instruções relacionadas. Depois de concluir uma seção, você poderá comparar o código com o código em step_x_completed.
Para simplificar, adicionamos alguns códigos básicos para a lista de vídeos e um ExoPlayer para ver o conteúdo dentro do app. Isso criará um esqueleto básico de um app para TV, o que está fora do escopo deste codelab.
Nosso objetivo aqui é aprender a adicionar, remover e atualizar os vídeos concluídos e não concluídos no canal "Assistir a seguir" e gerar um novo engajamento para o app.
Estes são os principais componentes do app:
FileVideoRepository
é a classe para carregar e consultar metadados de vídeo.PlaybackFragment
é o fragmento de reprodução de vídeo.WatchNextPlaybackStateListener
é um listener de mudança de estado de reprodução, que detecta eventos de reprodução e aciona operações relacionadas.WatchNextWorker
é um worker responsável por atualizar o canal "Assistir a seguir".WatchNextHelper
é uma classe auxiliar que simplifica o trabalho com o canal "Assistir a seguir".
Este codelab usa dados de mídia em res/raw/api.json
para preencher as entradas de "Assistir a seguir".
Executar o projeto inicial
Execute step_1. Caso encontre problemas, consulte a documentação sobre como começar.
- Conecte o Android TV ou inicie o emulador.
- Selecione a configuração step_1, selecione seu dispositivo Android e pressione o botão run na barra de menus.
- Você vai notar um contorno simples do app de TV com quatro coleções de vídeos, semelhante à captura de tela abaixo.
- Navegue pela tela principal do app e se familiarize com o app de TV de referência. Existem quatro categorias de vídeo:
- Clipes de carregamento rápido
- Clipes diversos
- A Família Buscapé: alguns episódios de duas temporadas diferentes
- Filmes do Charlie Chaplin
- Clique em um dos episódios de programa de TV da categoria Família Buscapé e assista ao episódio. Neste codelab, você vai aprender a adicionar episódios desse programa de TV ao canal "Assistir a seguir".
O que você aprendeu
Na introdução, você aprendeu sobre:
- a estrutura de código e as classes mais importantes usadas neste codelab;
- a configuração e a execução do app de exemplo.
Qual é a próxima etapa?
Diretrizes de qualidade do canal "Assistir a seguir"
3. Entender as diretrizes de qualidade do canal "Assistir a seguir"
Para oferecer uma experiência melhor na tela inicial, todos os apps que adicionam conteúdo ao "Assistir a seguir" precisam se comportar de forma consistente.
Mais especificamente, existem cenários que precisam ser considerados pelos desenvolvedores para processar os episódios de programas de TV. O Google tem uma lista que resume as diretrizes de qualidade do canal "Assistir a seguir".
Como criar o recurso "Assistir a seguir" de acordo com os padrões de qualidade do Google
Quando o Google avalia o recurso "Assistir a seguir", os seguintes pontos são verificados:
- O programa é adicionado ao canal "Assistir a seguir" quando pausado ou interrompido.
- O app consegue retomar a reprodução a partir do "Assistir a seguir".
- O app atualiza a posição de reprodução no canal "Assistir a seguir" o mais rápido possível.
- O programa é removido da seção "Assistir a seguir" quando a reprodução é concluída.
- O próximo episódio é adicionado quando o episódio atual é concluído.
- O app não adiciona conteúdos com que o usuário não interagiu ao canal "Assistir a seguir".
- O app envia todo o conteúdo não concluído para o canal "Assistir a seguir".
- O app define os metadados corretos e completos, por exemplo, números de temporadas ou episódios.
- O app não adiciona vários episódios da mesma série de TV.
Explicações de cada requisito de qualidade
- O programa é adicionado ao canal "Assistir a seguir" quando pausado ou interrompido.
- Os apps precisam adicionar filmes e programas de TV tradicionais à linha "Assistir a seguir" quando a reprodução não é concluída.
- O app consegue retomar a reprodução a partir do "Assistir a seguir".
- O conteúdo adicionado ao canal "Assistir a seguir" retoma a reprodução de onde ela foi interrompida. O vídeo precisa iniciar a reprodução imediatamente após o conteúdo ser carregado.
- O app atualiza a posição de reprodução no canal "Assistir a seguir" o mais rápido possível.
- O app precisa acompanhar o progresso da reprodução e atualizar o programa no canal "Assistir a seguir" de acordo com a posição mais recente do momento em que o usuário interrompeu o vídeo.
- O programa é removido da seção "Assistir a seguir" quando a reprodução é concluída.
- O app precisa se comportar bem e fazer uma limpeza. A linha "Assistir a seguir" é compartilhada por todos os apps, e queremos garantir que o conteúdo dela seja preciso para manter a confiança do usuário.
- O próximo episódio é adicionado quando o episódio atual é concluído.
- Quando o usuário assiste a uma série de TV, o app precisa facilitar a continuidade do conteúdo, adicionando o próximo episódio da série à linha "Assistir a seguir".
- O app não adiciona conteúdos com que o usuário não interagiu ao canal "Assistir a seguir".
- De acordo com as diretrizes do canal "Assistir a seguir", o app só pode adicionar um filme ou episódio de um programa de TV a esse canal caso o usuário já tenha começado a assistir o conteúdo.
- Não é recomendável adicionar trailers ou videoclipes ao canal "Assistir a seguir" porque eles não geram muito engajamento.
- O app envia todo o conteúdo não concluído para o canal "Assistir a seguir".
- Os provedores não podem limitar de forma artificial o número de cards enviados para o canal "Assistir a seguir". Caso o usuário tenha um conteúdo não concluído, os provedores precisam enviá-lo para a linha "Assistir a seguir".
- O app define os metadados corretos e completos.
- Verifique se os metadados associados ao episódio estão corretos.
- O número do episódio, o número da temporada e o título precisam estar certos.
- A barra de progresso precisa ser proporcional ao período já assistido.
- A imagem do episódio ou da série precisa estar presente no bloco.
- O app precisa evitar adicionar vários episódios da mesma série.
- O app precisa ter no máximo uma entrada de "Assistir a seguir" para cada série de TV. Caso o usuário assista metade de dois episódios diferentes, o canal só exibirá o que foi assistido por último.
Esses requisitos de qualidade ajudam o app a oferecer uma ótima experiência do usuário no canal "Assistir a seguir".
Agora, vamos começar a criar os recursos "Assistir a seguir" considerando essas diretrizes de qualidade.
O que você aprendeu
Nesta seção, você aprendeu a:
- os requisitos de qualidade do canal "Assistir a seguir".
Qual é a próxima etapa?
Adicionar um episódio não concluído ao canal "Assistir a seguir"
4. Adicionar conteúdos não concluídos ao canal "Assistir a seguir"
Começaremos com a funcionalidade básica: adicionar um episódio não concluído ao canal "Assistir a seguir".
Este codelab vai ajudar você a criar um WatchNextProgram
e preencher os metadados corretos, como os números do episódio e da temporada, tipo de vídeo etc. A entrada "Assistir a seguir" é atualizável, o que garante que ela esteja de acordo com as informações mais recentes da posição de reprodução. Dessa forma, o usuário consegue retomar a reprodução clicando no programa.
Os assuntos a seguir serão abordados nesta seção:
- O programa é adicionado ao canal "Assistir a seguir" quando pausado ou interrompido.
- O app consegue retomar a reprodução a partir do "Assistir a seguir".
- O app atualiza a posição da reprodução no canal "Assistir a seguir" o mais rápido possível.
- O app define os metadados corretos e completos.
Adicionar um vídeo não concluído: a diferença entre filmes e episódios
O procedimento para adicionar um filme ou um episódio ao canal "Assistir a seguir" é muito parecido. A única diferença é que os metadados são diferentes para cada um deles.
Por exemplo, para episódios, existem métodos de metadados específicos em WatchNextProgram.Builder
, como setEpisodeNumber, setSeasonNumber(),
setSeasonTitle()
e setEpisodeTitle()
.
Adicionar um vídeo não concluído (filme ou episódio) ao canal "Assistir a seguir"
Para adicionar um vídeo não concluído ao canal "Assistir a seguir", os desenvolvedores podem usar WatchNextProgram.Builder
para criar uma instância de WatchNextProgram
e chamar PreviewChannelHelper.publishWatchNextProgram
para publicá-la.
Primeiro, crie uma instância do builder de WatchNextProgram
e defina todos os metadados para descrever o vídeo.
Ao procurar pelo método setBuilderMetadata
em PlayNextHelper.kt
em step_1, copie e cole o seguinte código entre os comentários Step 1.1 - Set video metadata for WatchNextProgram.
.
WatchNextHelper.kt
builder.setType(type)
.setWatchNextType(watchNextType)
.setLastPlaybackPositionMillis(watchPosition)
.setLastEngagementTimeUtcMillis(System.currentTimeMillis())
.setTitle(video.name)
.setDurationMillis(duration.toMillis().toInt())
.setPreviewVideoUri(Uri.parse(video.videoUri))
.setDescription(video.description)
.setPosterArtUri(Uri.parse(video.thumbnailUri))
// Intent uri used to deep link video when the user clicks on watch next item.
.setIntentUri(Uri.parse(video.uri))
.setInternalProviderId(video.id)
// Use the contentId to recognize the same content across different channels.
.setContentId(video.id)
if (type == TYPE_TV_EPISODE) {
builder.setEpisodeNumber(video.episodeNumber.toInt())
.setSeasonNumber(video.seasonNumber.toInt())
// User TV series name and season number to generate a fake season name.
.setSeasonTitle(context.getString(
R.string.season, video.category, video.seasonNumber))
// Use the name of the video as the episode name.
.setEpisodeTitle(video.name)
// Use TV series name as the tile, in this sample,
// we use category as a fake TV series.
.setTitle(video.category)
}
Leia todo o código na etapa 1.1 e tente entender o motivo por que estamos configurando esses metadados.
setLastPlaybackPositionMillis()
esetDurationMillis()
ajudam a mostrar o progresso de reprodução correto e a atualizá-lo quando o usuário interage com o vídeo.setLastEngagementTimeUtcMillis()
define a marcação de tempo assistido pelo usuário, o que ajuda o canal "Assistir a seguir" a priorizar as entradas.
Adicionar um filme não concluído ao canal "Assistir a seguir"
Podemos usar WATCH_NEXT_TYPE_NEXT
para adicionar um filme não concluído ao canal "Assistir a seguir".
Definir metadados do filme: título e descrição
Para filmes, é necessário definir o título e a descrição, além de outros atributos, para que o usuário saiba que está assistindo o conteúdo certo sem clicar no vídeo.
builder.setType(type)
.setWatchNextType(watchNextType)
.setLastPlaybackPositionMillis(watchPosition)
.setLastEngagementTimeUtcMillis(System.currentTimeMillis())
.setTitle(video.name)
.setDurationMillis(duration.toMillis().toInt())
.setPreviewVideoUri(Uri.parse(video.videoUri))
.setDescription(video.description)
.setPosterArtUri(Uri.parse(video.thumbnailUri))
...
Captura de tela de exemplo de um filme.
Adicionar um episódio não concluído ao canal "Assistir a seguir"
Existem quatro tipos que podem ser usados para setWatchNextType()
. Use WATCH_NEXT_TYPE_CONTINUE
para episódios não concluídos e WATCH_NEXT_TYPE_NEXT
para o próximo episódio.
Definir metadados de episódios: número ou título do episódio e da temporada
Para os episódios de programas de TV, é necessário definir o número do episódio e o número da temporada, para que o usuário saiba que está assistindo ao episódio certo sem clicar no vídeo.
if (type == TYPE_TV_EPISODE) {
Builder.setType(PreviewPrograms.TYPE_EPISODE)
.setEpisodeNumber(video.episodeNumber.toInt())
.setSeasonNumber(video.seasonNumber.toInt())
// Use TV series name and season number to generate a fake season name.
.setSeasonTitle(context.getString(
R.string.season, video.category, video.seasonNumber))
// Use the name of the video as the episode name.
.setEpisodeTitle(video.name)
// Use TV series name as the tile, in this sample,
// we use category as a fake TV series.
.setTitle(video.category)
}
SeasonTitle, EpisodeTitle e Title precisam ser definidos corretamente. Cada episódio tem um título próprio que descreve o conteúdo dele. Podemos usar essa informação em EpisodeTitle. Use o título da série de TV no atributo do título de programa de TV. Assim, os usuários saberão a que programa o episódio pertence. Se existir um título de temporada, use essa informação em SeasonTitle. Caso contrário, é possível usar uma combinação do nome da série e do número da temporada, por exemplo, <nome da série de TV> <número da temporada>.
Captura de tela de exemplo de um episódio.
Retomar a reprodução
setLastPlaybackPositionMillis(watchPosition)
é usado para transmitir a marcação de tempo do momento em que o usuário fechou o filme ou episódio. Esse progresso vai ser exibido no card "Assistir a seguir". No app de TV de referência, o código usa WatchProgressDatabase
para rastrear o progresso da reprodução de cada vídeo. Isso permite que os usuários continuem assistindo a partir do ponto anterior, independentemente da forma como navegaram até o vídeo.
De acordo com as Diretrizes de reprodução das ações de assistir, o episódio precisa começar imediatamente após o carregamento do vídeo. Não é necessário exibir as informações da série de TV novamente, porque o usuário já começou a assisti-la.
Em seguida, chame PreviewChannelHelper.publishWatchNextProgram
para publicá-lo no canal "Assistir a seguir". Pesquise por "Step 1.2
" no mesmo arquivo e cole o seguinte código:
WatchNextHelper.kt
try {
programId = PreviewChannelHelper(context)
.publishWatchNextProgram(updatedProgram)
Timber.v("Added New program to Watch Next row: ${updatedProgram.title}")
} catch (exc: IllegalArgumentException) {
Timber.e(
exc, "Unable to add program to Watch Next row. ${exc.localizedMessage}"
)
exc.printStackTrace()
}
Atualizar o progresso de reprodução
Se já existir um card "Assistir a seguir" no canal "Assistir a seguir", o app precisará mantê-lo atualizado caso o usuário assista ao vídeo por mais tempo para que ele reflita o progresso mais recente.
Ao atualizar um WatchNextProgram
, use a mesma classe de builder para criar um WatchNextProgram
e chame updateWatchNextProgram
de PreviewChannelHelper
para atualizar a entrada existente. Cole o seguinte código em "Step 1.3
" em WatchNextHelper.kt
.
WatchNextHelper.kt
programId = existingProgram.id
PreviewChannelHelper(context).updateWatchNextProgram(updatedProgram, programId)
Conferir o resultado
Analise o código, compare as mudanças feitas com a fonte em step_1_completed e execute step_1_completed. Assista a um trecho de um episódio e verifique se ele foi adicionado ao canal "Assistir a seguir".
Validações
- ✅ PASSED: o programa é adicionado ao canal "Assistir a seguir" quando pausado ou interrompido.
- ✅ PASSED: o app consegue retomar a reprodução de acordo com a entrada de "Assistir a seguir".
- ✅ PASSED: o app atualiza a posição de reprodução no canal "Assistir a seguir" o mais rápido possível.
- ✅ PASSED: o app define os metadados corretos e completos.
- ✅ PASSED: o app envia todo o conteúdo não concluído ao canal "Assistir a seguir".
- ❗ FAILED: o programa é removido do canal "Assistir a seguir" quando a reprodução é concluída.
- ❗ FAILED: o próximo episódio é adicionado quando o episódio atual é concluído.
- ❗ FAILED: o app não adiciona conteúdos com que o usuário não interagiu ao canal "Assistir a seguir".
- ❗ FAILED: o app não adiciona vários episódios da mesma série de TV.
O que você aprendeu
Nesta seção, você aprendeu a:
- criar um
WatchNextProgram
; - inserir ou atualizar WatchNextProgram no canal "Assistir a seguir";
- atualizar o progresso da reprodução;
- retomar a reprodução;
- definir os metadados corretos para um episódio de programa de TV.
Qual é a próxima etapa?
Adicionar um episódio não concluído ao canal "Assistir a seguir"
5. Remover conteúdo (filmes ou episódios) do canal "Assistir a seguir" quando a reprodução for concluída
Os cards no canal "Assistir a seguir" são ordenados por último tempo de engajamento. O vídeo com que o usuário interagiu por último é colocado na frente do canal. O app precisa remover o programa do canal "Assistir a seguir" depois que o usuário termina de assisti-lo e promover os conteúdos mais relevantes.
Os desenvolvedores precisam monitorar o progresso de reprodução do vídeo. Quando o usuário termina de assistir a um vídeo, o app precisa removê-lo do canal "Assistir a seguir".
Observação: a mesma lógica pode ser usada para remover um filme ou episódio do canal "Assistir a seguir".
Remover WatchNextProgram
Para excluir uma entrada do canal "Assistir a seguir", os desenvolvedores precisam encontrar o WatchNextProgram
correto e usar o URI do programa para excluí-lo do provedor de conteúdo. Para fazer isso, é necessário que WatchNextProgram
corresponda às entidades de vídeo no banco de dados do desenvolvedor. Podemos aproveitar o campo internalProviderId, definir um identificador de vídeo exclusivo e vinculá-lo a uma das entidades no banco de dados do desenvolvedor.
Primeiramente, encontre o WatchNextProgram
correto procurando pelo ID do vídeo. É possível acessar o internalProviderId em WatchNextProgram.
getInternalProviderId
ou acessá-lo usando o provedor de conteúdo WatchNextProgram
. Em seguida, remova-o do canal "Assistir a seguir" com o URI.
Pesquise por "Step 2.1
" e depois copie e cole o seguinte:
WatchNextHelper.kt
val foundProgram = getWatchNextProgramByVideoId(video.id, context)
if (foundProgram == null) {
Timber.e(
"Unable to delete. No program found with videoID ${video.id}"
)
return null
}
// Use the found program's URI to delete it from the content resolver
return foundProgram.let {
val programUri = TvContractCompat.buildWatchNextProgramUri(it.id)
// delete returns the number of rows deleted.
val deleteCount = context.contentResolver.delete(
programUri, null, null
)
if (deleteCount == 1) {
Timber.v("Content successfully removed from Watch Next")
programUri
} else {
Timber.e("Content failed to be removed from Watch Next, delete count $deleteCount")
null
}
}
Caso queira remover vários WatchNextProgram
s de uma só vez, é recomendável solicitar uma operação em lote para otimizar as visitas ao provedor de conteúdo da TV. Pesquise por "Step 2.2
" e depois copie e cole o seguinte snippet de código em WatchNextHelper.kt
.
WatchNextHelper.kt
val foundPrograms = getWatchNextProgramByVideoIds(videos.map { it.id }, context)
val operations = foundPrograms.map {
val programUri = TvContractCompat.buildWatchNextProgramUri(it.id)
ContentProviderOperation.newDelete(programUri).build()
} as ArrayList<ContentProviderOperation>
val results = context.contentResolver.applyBatch(TvContractCompat.AUTHORITY, operations)
results.forEach { result ->
if (result.count != 1) {
Timber.e("Content failed to be removed from Watch Next: ${result.uri}")
}
}
De acordo com as diretrizes do canal "Assistir a seguir", o episódio precisa ser removido quando o usuário termina de assisti-lo. O usuário terá "concluído" um episódio se os créditos finais começarem. Nesse caso, o episódio não pode ser adicionado ao canal "Assistir a seguir" e precisa ser removido caso já tenha sido adicionado. É possível determinar esse estado usando uma tecnologia de detecção automática de créditos finais ou uma aproximação de acordo com a duração do conteúdo, por exemplo, quando houver menos de três minutos restantes no episódio.
Ao analisar o método handleWatchNextForEpisodes()
em WatchNextHelper.kt
, é possível encontrar o seguinte snippet:
WatchNextHelper.kt
video.isAfterEndCreditsPosition(watchPosition.toLong()) -> {
removeVideoFromWatchNext(context, video)
...
}
Neste codelab, usamos VIDEO_COMPLETED_DURATION_MAX_PERCENTAGE
para simular a posição da cena de crédito. Você pode substituir o código em isAfterEndCreditsPosition()
por sua própria lógica.
Conferir o resultado
Analise o código, compare as mudanças feitas com a fonte em step_2_completed, execute step_2_completed e assista a um episódio. Verifique se ele foi removido do canal "Assistir a seguir" depois de concluído.
Validação
- ✅ PASSED: o programa é adicionado ao canal "Assistir a seguir" quando pausado ou interrompido.
- ✅ PASSED: o app consegue retomar a reprodução de acordo com a entrada de "Assistir a seguir".
- ✅ PASSED: o app atualiza a posição de reprodução no canal "Assistir a seguir" o mais rápido possível.
- ✅ PASSED: o app define os metadados corretos e completos.
- ✅ PASSED: o app envia todo o conteúdo não concluído ao canal "Assistir a seguir".
- ✅ PASSED: o programa é removido do canal "Assistir a seguir" quando a reprodução é concluída.
- ❗ FAILED: o próximo episódio é adicionado quando o episódio atual é concluído.
- ❗ FAILED: o app não adiciona conteúdos com que o usuário não interagiu ao canal "Assistir a seguir".
- ❗ FAILED: o app não adiciona vários episódios da mesma série de TV.
O que você aprendeu
Na introdução, você aprendeu a:
- identificar a cena dos créditos de programas de TV;
- encontrar
WatchNextProgram
pelo ID do vídeo; - excluir um único
WatchNextProgram
; - excluir vários
WatchNextProgram
.
Qual é a próxima etapa?
Adicionar o próximo episódio ao canal "Assistir a seguir"
6. Adicionar o próximo episódio
Ao contrário dos filmes, os programas de TV têm mais de uma temporada e vários episódios em cada uma. Quando um usuário terminar de assistir a um episódio, em vez de apenas remover o episódio do canal "Assistir a seguir", o recomendável é substituí-lo pelo próximo. O episódio que será assistido na sequência pode ser o próximo da mesma temporada ou o primeiro episódio da temporada seguinte, caso o usuário tenha assistido ao último episódio da temporada atual.
Ao adicionar o próximo episódio ao canal "Assistir a seguir", defina o tipo Watch Next como WATCH_NEXT_TYPE_NEXT
. Isso indica que o episódio não corresponde a um programa assistido anteriormente, mas sim a um conteúdo completamente novo que o usuário poderá acompanhar. Os apps precisam permitir que o usuário assista ao próximo episódio desde o início. Pesquise por "TODO: Step 3.1 - Add next episode from TV series.
" e depois copie e cole o código a seguir na etapa 3.1:
WatchNextHelper.kt
videoRepository.getNextEpisodeInSeries(video)?.let {
insertOrUpdateVideoToWatchNext(
it,
0,
WATCH_NEXT_TYPE_NEXT,
context
)
newWatchNextVideo = it
}
O próximo episódio é capturado pelo método getNextEpisodeInSeries()
.
Próximo episódio da mesma temporada
Caso a temporada atual ainda tenha mais episódios, o app definirá o episódio seguinte como o próximo a ser assistido.
Primeiro episódio da temporada seguinte
Caso o usuário tenha terminado de assistir a temporada atual, mas haja uma nova temporada disponível, o app definirá o primeiro episódio da temporada seguinte como o próximo a ser assistido.
Lançamento de um novo episódio
Caso não haja mais episódios, o app não precisará adicionar o próximo episódio. No entanto, quando um novo episódio for disponibilizado, é recomendável enviá-lo para o lado do cliente e adicioná-lo ao canal "Assistir a seguir". Novos episódios precisam usar WATCH_NEXT_TYPE_NEW
como o tipo de WatchNextProgram. Essa solução precisa de notificações push de servidor, que não são abordadas neste codelab.
Conferir o resultado
Analise o código, compare as mudanças feitas com a fonte em step_3_completed, execute step_3_completed e assista a um episódio. Confira se o próximo episódio foi adicionado ao canal "Assistir a seguir" depois que você terminou de assisti-lo.
Validação
- ✅ PASSED: o programa é adicionado ao canal "Assistir a seguir" quando pausado ou interrompido.
- ✅ PASSED: o app consegue retomar a reprodução de acordo com a entrada de "Assistir a seguir".
- ✅ PASSED: o app atualiza a posição de reprodução no canal "Assistir a seguir" o mais rápido possível.
- ✅ PASSED: o app define os metadados corretos e completos.
- ✅ PASSED: o app envia todo o conteúdo não concluído ao canal "Assistir a seguir".
- ✅ PASSED: o programa é removido do canal "Assistir a seguir" quando a reprodução é concluída.
- ✅ PASSED: o próximo episódio é adicionado quando o episódio atual é concluído.
- ❗ FAILED: o app não adiciona conteúdos com que o usuário não interagiu ao canal "Assistir a seguir".
- ❗ FAILED: o app não adiciona vários episódios da mesma série de TV.
O que você aprendeu
Nesta seção, você aprendeu a:
- como selecionar o próximo episódio;
- como adicionar o próximo episódio da série de TV
Qual é a próxima etapa?
Entender o interesse do usuário
7. Entender o interesse do usuário
Para manter o foco dos usuários no conteúdo mais relevante do canal "Assistir a seguir", existem outros fatores que o app precisa considerar ao adicionar ou remover um episódio de um programa de TV.
Vários episódios da mesma série
Existem vários motivos para que o usuário tenha mais de um episódio não concluído em um momento específico. Por exemplo:
- A série de TV está disponível em vários apps ou está no ar no momento.
- O usuário optou por acelerar e pular alguns conteúdos.
O canal "Assistir a seguir" tem entradas muito limitadas na tela inicial. Por esse motivo, o Google sugere que os apps mantenham no máximo um episódio de cada série de TV nesse canal. O episódio exibido precisa ser o que foi assistido mais recentemente pelo usuário.
Na classe WatchNextHelper
, isso é processado em handlePlayNextForEpisode()
. Pesquise por "Step 4.1
" e depois copie e cole o seguinte código na área em branco da etapa 4.1.
WatchNextHelper.kt
newWatchNextVideo?.let { videoToKeep ->
videoRepository.getAllVideosFromSeries(videoToKeep.seriesUri)?.let { allEpisodes ->
filterWatchNextVideos(allEpisodes, context)
?.let { watchedEpisodes ->
removeVideosFromWatchNext(
context, watchedEpisodes.filter { it.id != videoToKeep.id })
}
}
}
Na etapa 4.1, continuamos rastreando o episódio que foi assistido pelo usuário mais recentemente, removendo todos os outros episódios da mesma série de TV. Como essa etapa remove vários episódios de uma só vez, criamos um novo método removeVideosFromWatchNext()
para aproveitar a operação em lote do provedor de conteúdo do Android.
Conteúdo com menos interação
De acordo com as diretrizes do canal "Assistir a seguir", um episódio só poderá ser adicionado ao canal se o usuário tiver começado a assisti-lo. Considera-se que um episódio foi iniciado caso o usuário tenha assistido mais de dois minutos. Pesquise por "Step 4.2
" e depois copie e cole o código a seguir na área da etapa 4.2.
WatchNextHelper.kt
val durationInMilliSeconds = duration.toMillis().toInt()
// Return true if either X minutes or Y % have passed
// Following formatting spans over multiple lines to accommodate max 100 limit
val watchNextMinStartedMillis = TimeUnit.MINUTES.toMillis(WATCH_NEXT_STARTED_MIN_MINUTES)
// Check if either X minutes or Y% has passed
val hasVideoStarted =
(currentPosition >= (durationInMilliSeconds * WATCH_NEXT_STARTED_MIN_PERCENTAGE)) or
(currentPosition >= watchNextMinStartedMillis)
val hasVideoStartedWithValidPosition =
((currentPosition <= durationInMilliSeconds) and hasVideoStarted)
Timber.v(
"Has video started: %s, duration: %s, watchPosition: %s",
hasVideoStartedWithValidPosition,
duration,
currentPosition
)
return hasVideoStartedWithValidPosition
Conferir o resultado
Analise o código, compare as mudanças feitas com a fonte em step_4_completed, execute step_4_completed e assista a um episódio. Confira se:
- o código remove os outros episódios da série de TV;
- só adiciona conteúdos que o usuário começou a ver ao canal "Assistir a seguir".
Validação
- ✅ PASSED: o programa é adicionado ao canal "Assistir a seguir" quando pausado ou interrompido.
- ✅ PASSED: o app consegue retomar a reprodução de acordo com a entrada de "Assistir a seguir".
- ✅ PASSED: o app atualiza a posição de reprodução no canal "Assistir a seguir" o mais rápido possível.
- ✅ PASSED: o app define os metadados corretos e completos.
- ✅ PASSED: o app envia todo o conteúdo não concluído ao canal "Assistir a seguir".
- ✅ PASSED: o programa é removido do canal "Assistir a seguir" quando a reprodução é concluída.
- ✅ PASSED: o próximo episódio é adicionado quando o episódio atual é concluído.
- ✅ PASSED: o app não adiciona conteúdos com que o usuário não interagiu ao canal "Assistir a seguir".
- ✅ PASSED: o app não adiciona vários episódios da mesma série de TV.
O que você aprendeu
Nesta seção, você aprendeu a:
- evitar a adição de vários episódios da mesma série de TV;
- evitar a adição de conteúdos com que houve menos interação.
Qual é a próxima etapa?
Parabéns
8. Parabéns
Parabéns! Você criou o canal "Assistir a seguir" para filmes e programas de TV e aprendeu todos os requisitos de qualidade dele.
Muito bem!