O Google está criando uma plataforma no dispositivo que organiza os apps dos usuários por categoria e possibilita uma nova experiência imersiva para consumo e descoberta de conteúdo personalizado de apps. Essa experiência em tela cheia oferece aos parceiros dos desenvolvedores uma oportunidade de mostrar o melhor conteúdo avançado em um canal dedicado fora do app.
Este guia contém instruções para que os parceiros dos desenvolvedores integrem conteúdo de vídeo, usando o SDK Engage para preencher essa nova área e as plataformas do Google.
Detalhe de integração
Terminologia
Essa integração inclui os três tipos de cluster a seguir: recomendação, continuação e destaque.
Os clusters de recomendação mostram sugestões personalizadas de conteúdo para assistir de um parceiro de desenvolvedor específico.
As recomendações têm a seguinte estrutura:
Cluster de recomendação: uma visualização de interface que contém um grupo de recomendações do mesmo parceiro do desenvolvedor.
Entidade: um objeto que representa um único item em um cluster. Uma entidade pode ser um filme, um programa de TV, uma série de TV, um vídeo ao vivo e muito mais. Consulte a seção Fornecer dados da entidade para conferir uma lista dos tipos de entidade aceitas.
O cluster de continuação mostra vídeos inacabados e episódios relevantes recém-lançados de vários parceiros de desenvolvedores em um único grupo de interfaces. Cada parceiro de desenvolvedor pode transmitir no máximo 10 entidades no cluster de continuação. Pesquisas demonstram que recomendações personalizadas, além de conteúdo de continuação personalizado, criam o melhor engajamento do usuário.
O cluster de destaque mostra uma seleção de entidades de vários parceiros de desenvolvimento em um único grupo de interfaces. Há um único cluster de destaque, exibido perto da parte de cima da interface, com um posicionamento prioritário acima de todos os clusters de recomendação. Cada parceiro de desenvolvedor pode transmitir até 10 entidades no cluster de destaque.
Pré-trabalho
Nível mínimo da API: 19
Adicione a biblioteca com.google.android.engage:engage-core
ao app:
dependencies {
// Make sure you also include that repository in your project's build.gradle file.
implementation 'com.google.android.engage:engage-core:1.5.2'
}
Para mais informações, consulte Visibilidade de pacotes no Android 11.
Resumo
O design é baseado na implementação de um serviço vinculado.
Os dados que um cliente pode publicar estão sujeitos aos seguintes limites para diferentes tipos de clusters:
Tipo de cluster | Limites de cluster | Limites máximos de entidades em um cluster |
---|---|---|
Clusters de recomendação | No máximo 5 | No máximo 50 |
Cluster de continuação | No máximo 1 | No máximo 10 |
Cluster de destaque | No máximo 1 | No máximo 10 |
Etapa 0: migração da integração do SDK Media Home
Mapear modelos de dados da integração atual
Se você estiver migrando de uma integração do Media Home, a tabela a seguir descreve como mapear modelos de dados em SDKs existentes para o novo SDK Engage:
Equivalente de integração do MediaHomeVideoContract | Equivalente de integração do SDK Engage |
---|---|
com.google.android.mediahome.video.PreviewChannel
|
com.google.android.engage.common.datamodel.RecommendationCluster
|
com.google.android.mediahome.video.PreviewChannel.Builder
|
com.google.android.engage.common.datamodel.RecommendationCluster.Builder
|
com.google.android.mediahome.video.PreviewChannelHelper
|
com.google.android.engage.video.service.AppEngageVideoClient
|
com.google.android.mediahome.video.PreviewProgram |
Dividido em classes separadas: EventVideo ,
LiveStreamingVideo , Movie ,
TvEpisode , TvSeason , TvShow ,
VideoClipEntity
|
com.google.android.mediahome.video.PreviewProgram.Builder
|
Dividido em builders em classes separadas: EventVideo ,
LiveStreamingVideo , Movie ,
TvEpisode , TvSeason , TvShow ,
VideoClipEntity
|
com.google.android.mediahome.video.VideoContract |
Não é mais necessário. |
com.google.android.mediahome.video.WatchNextProgram |
Dividido em atributos em classes separadas:
EventVideoEntity , LiveStreamingVideoEntity ,
MovieEntity , TvEpisodeEntity ,
TvSeasonEntity , TvShowEntity ,
VideoClipEntity |
com.google.android.mediahome.video.WatchNextProgram.Builder
|
Dividido em atributos em classes separadas:
EventVideoEntity , LiveStreamingVideoEntity ,
MovieEntity , TvEpisodeEntity ,
TvSeasonEntity , TvShowEntity ,
VideoClipEntity |
Como publicar clusters no SDK Media Home e no SDK Engage
Com o SDK Media Home, clusters e entidades foram publicados usando APIs separadas:
// 1. Fetch existing channels
List<PreviewChannel> channels = PreviewChannelHelper.getAllChannels();
// 2. If there are no channels, publish new channels
long channelId = PreviewChannelHelper.publishChannel(builder.build());
// 3. If there are existing channels, decide whether to update channel contents
PreviewChannelHelper.updatePreviewChannel(channelId, builder.build());
// 4. Delete all programs in the channel
PreviewChannelHelper.deleteAllPreviewProgramsByChannelId(channelId);
// 5. publish new programs in the channel
PreviewChannelHelper.publishPreviewProgram(builder.build());
Com o SDK Engage, a publicação de clusters e entidades é combinada em uma única chamada de API. Todas as entidades que pertencem a um cluster são publicadas com ele:
Kotlin
RecommendationCluster.Builder() .addEntity(MOVIE_ENTITY) .addEntity(MOVIE_ENTITY) .addEntity(MOVIE_ENTITY) .setTitle("Top Picks For You") .build()
Java
new RecommendationCluster.Builder() .addEntity(MOVIE_ENTITY) .addEntity(MOVIE_ENTITY) .addEntity(MOVIE_ENTITY) .setTitle("Top Picks For You") .build();
Etapa 1: fornecer dados da entidade
O SDK definiu entidades diferentes para representar cada tipo de item. Oferecemos suporte às seguintes entidades na categoria "Assistir":
O gráfico a seguir descreve os atributos e os requisitos de cada tipo.
MovieEntity
Atributo | Requisito | Observações |
---|---|---|
Name | Obrigatório | |
Poster images | Obrigatório | Pelo menos uma imagem é necessária e precisa ser fornecida com uma
proporção. Recomendamos o modo paisagem, mas é possível usar imagens em
modo retrato e paisagem para diferentes situações.
Consulte as orientações em Especificações de imagem. |
Playback uri | Obrigatório |
O link direto para o app do provedor para começar a assistir o filme. Observação: é possível usar links diretos para atribuição. Consulte as perguntas frequentes |
Info page uri | Opcional |
O link direto para o app do provedor para mostrar detalhes sobre o filme. Observação: é possível usar links diretos para atribuição. Consulte as perguntas frequentes |
Data de lançamento | Obrigatório | Em milissegundos de época. |
Availability | Obrigatório | AVAILABLE: o conteúdo está disponível para o usuário sem qualquer outra ação. FREE_WITH_SUBSCRIPTION: o conteúdo é disponibilizado depois que o usuário compra uma assinatura. PAID_CONTENT: o conteúdo requer a compra ou a locação. PURCHASED: o conteúdo foi comprado ou alugado pelo usuário. |
Offer price | Opcional | Texto livre |
Duration | Obrigatório | Em milissegundos. |
Genre | Obrigatório | Texto livre |
Content ratings | Obrigatório | Texto livre. Siga o padrão do setor. (Exemplo) |
Watch next type | Obrigatório sob certas condições | Precisa ser fornecido quando o item está no cluster de continuação e precisa ser de um dos quatro tipos a seguir: CONTINUE: o usuário já assistiu mais de um minuto desse conteúdo. NEW: o usuário assistiu a todos os episódios disponíveis de algum conteúdo em episódios, mas um novo episódio foi disponibilizado e há exatamente um episódio não assistido. Isso vale para programas de TV, partidas de futebol gravadas de uma série e assim por diante. NEXT: o usuário assistiu a um ou mais episódios completos de algum conteúdo, mas resta mais de um episódio ou exatamente um episódio sendo que esse último não é "NEW" (novo) e foi liberado antes que o usuário começasse a assistir ao conteúdo em episódios. WATCHLIST: o usuário optou por adicionar um filme, um evento ou uma série a uma lista de interesses para selecionar manualmente o que assistir em seguida. |
Last engagement time | Obrigatório sob certas condições | Precisa ser fornecido quando o item estiver no cluster de continuação. Em milissegundos da época. |
Last playback position time | Obrigatório sob certas condições | Precisa ser fornecido quando o item está no cluster de continuação e WatchNextType é CONTINUE. Em milissegundos de época. |
TvShowEntity
Atributo | Requisito | Observações |
---|---|---|
Name | Obrigatório | |
Poster images | Obrigatório | Pelo menos uma imagem é necessária e precisa ser fornecida com uma
proporção. Recomendamos o modo paisagem, mas é possível usar imagens em
modo retrato e paisagem para diferentes situações.
Consulte as orientações em Especificações de imagem. |
Info page uri | Obrigatório |
O link direto para o app do provedor para mostrar os detalhes do programa de TV. Observação: é possível usar links diretos para atribuição. Consulte as perguntas frequentes |
Playback uri | Opcional |
O link direto para o app do provedor para começar a assistir o programa de TV. Observação: é possível usar links diretos para atribuição. Consulte as perguntas frequentes |
First episode air date | Obrigatório | Em milissegundos de época. |
Latest episode air date | Opcional | Em milissegundos de época. |
Availability | Obrigatório | AVAILABLE: o conteúdo está disponível para o usuário sem qualquer outra ação. FREE_WITH_SUBSCRIPTION: o conteúdo é disponibilizado depois que o usuário compra uma assinatura. PAID_CONTENT: o conteúdo requer a compra ou a locação. PURCHASED: o conteúdo foi comprado ou alugado pelo usuário. |
Offer price | Opcional | Texto livre |
Season count | Obrigatório | Número inteiro positivo |
Genre | Obrigatório | Texto livre |
Content ratings | Obrigatório | Texto livre. Siga o padrão do setor. (Exemplo) |
Watch next type | Obrigatório sob certas condições | Precisa ser fornecido quando o item está no cluster de continuação e precisa ser de um dos quatro tipos a seguir: CONTINUE: o usuário já assistiu mais de um minuto desse conteúdo. NEW: o usuário assistiu a todos os episódios disponíveis de algum conteúdo em episódios, mas um novo episódio foi disponibilizado e há exatamente um episódio não assistido. Isso vale para programas de TV, partidas de futebol gravadas de uma série e assim por diante. NEXT: o usuário assistiu a um ou mais episódios completos de algum conteúdo, mas resta mais de um episódio ou exatamente um episódio sendo que esse último não é "NEW" (novo) e foi liberado antes que o usuário começasse a assistir ao conteúdo em episódios. WATCHLIST: o usuário optou por adicionar um filme, um evento ou uma série a uma lista de interesses para selecionar manualmente o que assistir em seguida. |
Last engagement time | Obrigatório sob certas condições | Precisa ser fornecido quando o item estiver no cluster de continuação. Em milissegundos da época. |
Last playback position time | Obrigatório sob certas condições | Precisa ser fornecido quando o item está no cluster de continuação e WatchNextType é CONTINUE. Em milissegundos de época. |
TvSeasonEntity
Atributo | Requisito | Observações |
---|---|---|
Name | Obrigatório | |
Poster images | Obrigatório | Pelo menos uma imagem é necessária e precisa ser fornecida com uma
proporção. Recomendamos o modo paisagem, mas é possível usar imagens em
modo retrato e paisagem para diferentes situações.
Consulte as orientações em Especificações de imagem. |
Info page uri | Obrigatório |
O link direto para o app do provedor para mostrar os detalhes da temporada do programa de TV. Observação: é possível usar links diretos para atribuição. Consulte as perguntas frequentes |
Playback uri | Opcional |
O link direto para o app do provedor para começar a assistir a temporada de programas de TV. Observação: é possível usar links diretos para atribuição. Consulte as perguntas frequentes |
Display Season number |
Opcional Disponível na v1.3.1 |
String |
First episode air date | Obrigatório | Em milissegundos de época. |
Latest episode air date | Opcional | Em milissegundos de época. |
Availability | Obrigatório | AVAILABLE: o conteúdo está disponível para o usuário sem qualquer outra ação. FREE_WITH_SUBSCRIPTION: o conteúdo é disponibilizado depois que o usuário compra uma assinatura. PAID_CONTENT: o conteúdo requer a compra ou a locação. PURCHASED: o conteúdo foi comprado ou alugado pelo usuário. |
Offer price | Opcional | Texto livre |
Episode count | Obrigatório | Número inteiro positivo |
Genre | Obrigatório | Texto livre |
Content ratings | Obrigatório | Texto livre. Siga o padrão do setor. (Exemplo) |
Watch next type | Obrigatório sob certas condições | Precisa ser fornecido quando o item está no cluster de continuação e precisa ser de um dos quatro tipos a seguir: CONTINUE: o usuário já assistiu mais de um minuto desse conteúdo. NEW: o usuário assistiu a todos os episódios disponíveis de algum conteúdo em episódios, mas um novo episódio foi disponibilizado e há exatamente um episódio não assistido. Isso vale para programas de TV, partidas de futebol gravadas de uma série e assim por diante. NEXT: o usuário assistiu a um ou mais episódios completos de algum conteúdo, mas resta mais de um episódio ou exatamente um episódio sendo que esse último não é "NEW" (novo) e foi liberado antes que o usuário começasse a assistir ao conteúdo em episódios. WATCHLIST: o usuário optou por adicionar um filme, um evento ou uma série a uma lista de interesses para selecionar manualmente o que assistir em seguida. |
Last engagement time | Obrigatório sob certas condições | Precisa ser fornecido quando o item estiver no cluster de continuação. Em milissegundos da época. |
Last playback position time | Obrigatório sob certas condições | Precisa ser fornecido quando o item está no cluster de continuação e WatchNextType é CONTINUE. Em milissegundos de época. |
TvEpisodeEntity
Atributo | Requisito | Observações |
---|---|---|
Name | Obrigatório | |
Poster images | Obrigatório | Pelo menos uma imagem é necessária e precisa ser fornecida com uma
proporção. Recomendamos o modo paisagem, mas é possível usar imagens em
modo retrato e paisagem para diferentes situações.
Consulte as orientações em Especificações de imagem. |
Playback uri | Obrigatório |
O link direto para o app do provedor para começar a assistir o episódio. Observação: é possível usar links diretos para atribuição. Consulte as perguntas frequentes |
Info page uri | Opcional |
O link direto para o app do provedor para mostrar detalhes sobre o episódio de programa de TV. Observação: é possível usar links diretos para atribuição. Consulte as perguntas frequentes |
Display Episode number |
Opcional Disponível na v1.3.1 |
String |
Air date | Obrigatório | Em milissegundos de época. |
Availability | Obrigatório | AVAILABLE: o conteúdo está disponível para o usuário sem qualquer outra ação. FREE_WITH_SUBSCRIPTION: o conteúdo é disponibilizado depois que o usuário compra uma assinatura. PAID_CONTENT: o conteúdo requer a compra ou a locação. PURCHASED: o conteúdo foi comprado ou alugado pelo usuário. |
Offer price | Opcional | Texto livre |
Duration | Obrigatório | Precisa ser um valor positivo em milissegundos. |
Genre | Obrigatório | Texto livre |
Content ratings | Obrigatório | Texto livre, siga o padrão do setor. (Exemplo) |
Watch next type | Obrigatório sob certas condições | Precisa ser fornecido quando o item está no cluster de continuação e precisa ser de um dos quatro tipos a seguir: CONTINUE: o usuário já assistiu mais de um minuto desse conteúdo. NEW: o usuário assistiu a todos os episódios disponíveis de algum conteúdo em episódios, mas um novo episódio foi disponibilizado e há exatamente um episódio não assistido. Isso vale para programas de TV, partidas de futebol gravadas de uma série e assim por diante. NEXT: o usuário assistiu a um ou mais episódios completos de algum conteúdo, mas resta mais de um episódio ou exatamente um episódio sendo que esse último não é "NEW" (novo) e foi liberado antes que o usuário começasse a assistir ao conteúdo em episódios. WATCHLIST: o usuário optou por adicionar um filme, um evento ou uma série a uma lista de interesses para selecionar manualmente o que assistir em seguida. |
Last engagement time | Obrigatório sob certas condições | Precisa ser fornecido quando o item estiver no cluster de continuação. Em milissegundos da época. |
Last playback position time | Obrigatório sob certas condições | Precisa ser fornecido quando o item está no cluster de continuação e WatchNextType é CONTINUE. Em milissegundos de época. |
LiveStreamingVideoEntity
Atributo | Requisito | Observações |
---|---|---|
Name | Obrigatório | |
Poster images | Obrigatório | Pelo menos uma imagem é necessária e precisa ser fornecida com uma
proporção. Recomendamos o modo paisagem, mas é possível usar imagens em
modo retrato e paisagem para diferentes situações.
Consulte as orientações em Especificações de imagem. |
Playback uri | Obrigatório |
O link direto para o app do provedor para começar a assistir o vídeo. Observação: é possível usar links diretos para atribuição. Consulte as perguntas frequentes |
Broadcaster | Obrigatório | Texto livre. |
Start time | Opcional | Em milissegundos de época. |
End time | Opcional | Em milissegundos de época. |
View count | Opcional | Texto livre. Precisa ser localizado. |
Watch next type | Obrigatório sob certas condições | Precisa ser fornecido quando o item está no cluster de continuação e precisa ser de um dos quatro tipos a seguir: CONTINUE: o usuário já assistiu mais de um minuto desse conteúdo. NEW: o usuário assistiu a todos os episódios disponíveis de algum conteúdo em episódios, mas um novo episódio foi disponibilizado e há exatamente um episódio não assistido. Isso vale para programas de TV, partidas de futebol gravadas de uma série e assim por diante. NEXT: o usuário assistiu a um ou mais episódios completos de algum conteúdo, mas resta mais de um episódio ou exatamente um episódio sendo que esse último não é "NEW" (novo) e foi liberado antes que o usuário começasse a assistir ao conteúdo em episódios. WATCHLIST: o usuário optou por adicionar um filme, um evento ou uma série a uma lista de interesses para selecionar manualmente o que assistir em seguida. |
Last engagement time | Obrigatório sob certas condições | Precisa ser fornecido quando o item estiver no cluster de continuação. Em milissegundos da época. |
Last playback position time | Obrigatório sob certas condições | Precisa ser fornecido quando o item está no cluster de continuação e WatchNextType é CONTINUE. Em milissegundos de época. |
VideoClipEntity
O objeto VideoClipEntity
representa uma entidade de vídeo de mídias sociais,
como o TikTok ou o YouTube.
Atributo | Requisito | Observações |
---|---|---|
Name | Obrigatório | |
Poster images | Obrigatório | Pelo menos uma imagem é necessária e precisa ser fornecida com uma
proporção. Recomendamos o modo paisagem, mas é possível usar imagens em
modo retrato e paisagem para diferentes situações.
Consulte as orientações em Especificações de imagem. |
Playback uri | Obrigatório |
O link direto para o app do provedor para começar a assistir o vídeo. Observação: é possível usar links diretos para atribuição. Consulte as perguntas frequentes |
Horário da criação | Obrigatório | Em milissegundos de época. |
Duration | Obrigatório | Precisa ser um valor positivo em milissegundos. |
Creator | Obrigatório | Texto livre. |
Creator image | Opcional | Imagem do avatar do criador |
View count | Opcional | Texto livre. Precisa ser localizado. |
Watch next type | Obrigatório sob certas condições | Precisa ser fornecido quando o item está no cluster de continuação e precisa ser de um dos quatro tipos a seguir: CONTINUE: o usuário já assistiu mais de um minuto desse conteúdo. NEW: o usuário assistiu a todos os episódios disponíveis de algum conteúdo em episódios, mas um novo episódio foi disponibilizado e há exatamente um episódio não assistido. Isso vale para programas de TV, partidas de futebol gravadas de uma série e assim por diante. NEXT: o usuário assistiu a um ou mais episódios completos de algum conteúdo, mas resta mais de um episódio ou exatamente um episódio sendo que esse último não é "NEW" (novo) e foi liberado antes que o usuário começasse a assistir ao conteúdo em episódios. WATCHLIST: o usuário optou por adicionar um filme, um evento ou uma série a uma lista de interesses para selecionar manualmente o que assistir em seguida. |
Last engagement time | Obrigatório sob certas condições | Precisa ser fornecido quando o item estiver no cluster de continuação. Em milissegundos da época. |
Last playback position time | Obrigatório sob certas condições | Precisa ser fornecido quando o item está no cluster de continuação e WatchNextType é CONTINUE. Em milissegundos de época. |
Especificações da imagem
A seção a seguir lista as especificações necessárias para recursos de imagem:
Formatos de arquivo
PNG, JPG, GIF estático, WebP
Tamanho máximo do arquivo
5.120 KB
Recomendações adicionais
- Área de segurança da imagem: posicione o conteúdo importante no centro da imagem, ocupando 80% do espaço.
Exemplo
Kotlin
var movie = MovieEntity.Builder() .setName("Avengers") .addPosterImage(Image.Builder() .setImageUri(Uri.parse("http://www.x.com/image.png")) .setImageHeightInPixel(960) .setImageWidthInPixel(408) .build()) .setPlayBackUri(Uri.parse("http://tv.com/playback/1")) .setReleaseDateEpochMillis(1633032895L) .setAvailability(ContentAvailability.AVAILABILITY_AVAILABLE) .setDurationMillis(12345678L) .addGenre("action") .addContentRating("R") .setWatchNextType(WatchNextType.TYPE_NEW) .setLastEngagementTimeMillis(1664568895L) .build()
Java
MovieEntity movie = new MovieEntity.Builder() .setName("Avengers") .addPosterImage( new Image.Builder() .setImageUri(Uri.parse("http://www.x.com/image.png")) .setImageHeightInPixel(960) .setImageWidthInPixel(408) .build()) .setPlayBackUri(Uri.parse("http://tv.com/playback/1")) .setReleaseDateEpochMillis(1633032895L) .setAvailability(ContentAvailability.AVAILABILITY_AVAILABLE) .setDurationMillis(12345678L) .addGenre("action") .addContentRating("R") .setWatchNextType(WatchNextType.TYPE_NEW) .setLastEngagementTimeMillis(1664568895L) .build();
Etapa 2: fornecer dados do cluster
É recomendável executar o job de publicação de conteúdo em segundo plano (por exemplo, usando o WorkManager) e programado com frequência ou por evento (por exemplo, toda vez que o usuário abrir o app ou adicionar algo ao carrinho).
AppEngagePublishClient
é responsável pela publicação de clusters. As seguintes
APIs estão disponíveis no cliente:
isServiceAvailable
publishRecommendationClusters
publishFeaturedCluster
publishContinuationCluster
publishUserAccountManagementRequest
updatePublishStatus
deleteRecommendationsClusters
deleteFeaturedCluster
deleteContinuationCluster
deleteUserManagementCluster
deleteClusters
isServiceAvailable
Essa API é usada para conferir se o serviço está disponível para integração e se o conteúdo pode ser apresentado no dispositivo.
Kotlin
client.isServiceAvailable.addOnCompleteListener { task -> if (task.isSuccessful) { // Handle IPC call success if(task.result) { // Service is available on the device, proceed with content publish // calls. } else { // Service is not available, no further action is needed. } } else { // The IPC call itself fails, proceed with error handling logic here, // such as retry. } }
Java
client.isServiceAvailable().addOnCompleteListener(task - > { if (task.isSuccessful()) { // Handle success if(task.getResult()) { // Service is available on the device, proceed with content publish // calls. } else { // Service is not available, no further action is needed. } } else { // The IPC call itself fails, proceed with error handling logic here, // such as retry. } });
publishRecommendationClusters
Essa API é usada para publicar uma lista de objetos RecommendationCluster
.
Kotlin
client.publishRecommendationClusters( PublishRecommendationClustersRequest.Builder() .addRecommendationCluster( RecommendationCluster.Builder() .addEntity(entity1) .addEntity(entity2) .setTitle("Top Picks For You") .build() ) .build() )
Java
client.publishRecommendationClusters( new PublishRecommendationClustersRequest.Builder() .addRecommendationCluster( new RecommendationCluster.Builder() .addEntity(entity1) .addEntity(entity2) .setTitle("Top Picks For You") .build()) .build());
Quando o serviço recebe a solicitação, as ações abaixo ocorrem em uma transação:
- Os dados do
RecommendationCluster
do parceiro do desenvolvedor são removidos. - Os dados da solicitação são analisados e armazenados no cluster de recomendação atualizado.
Em caso de erro, o pedido inteiro é rejeitado e o estado atual é mantido.
publishFeaturedCluster
Essa API é usada para publicar uma lista de objetos FeaturedCluster
.
Kotlin
client.publishFeaturedCluster( PublishFeaturedClusterRequest.Builder() .setFeaturedCluster( FeaturedCluster.Builder() .addEntity(entity1) .addEntity(entity2) .build()) .build())
Java
client.publishFeaturedCluster( new PublishFeaturedClustersRequest.Builder() .addFeaturedCluster( new FeaturedCluster.Builder() .addEntity(entity1) .addEntity(entity2) .build()) .build());
Quando o serviço recebe a solicitação, as ações abaixo ocorrem em uma transação:
- Os dados do
FeaturedCluster
do parceiro do desenvolvedor são removidos. - Os dados da solicitação são analisados e armazenados no cluster de destaque atualizado.
Em caso de erro, a solicitação inteira é rejeitada e o estado atual é mantido.
publishContinuationCluster
Essa API é usada para publicar um objeto ContinuationCluster
.
Kotlin
client.publishContinuationCluster( PublishContinuationClusterRequest.Builder() .setContinuationCluster( ContinuationCluster.Builder() .addEntity(entity1) .addEntity(entity2) .build()) .build())
Java
client.publishContinuationCluster( new PublishContinuationClusterRequest.Builder() .setContinuationCluster( new ContinuationCluster.Builder() .addEntity(entity1) .addEntity(entity2) .build()) .build());
Quando o serviço recebe a solicitação, as ações abaixo ocorrem em uma transação:
- Os dados do
ContinuationCluster
do parceiro do desenvolvedor são removidos. - Os dados da solicitação são analisados e armazenados no cluster de continuação atualizado.
Em caso de erro, a solicitação inteira é rejeitada e o estado atual é mantido.
publishUserAccountManagementRequest
Essa API é usada para publicar um card de login. A ação de login direciona os usuários à página de login do app para que ele possa publicar ou oferecer conteúdo mais personalizado.
Os metadados abaixo fazem parte do card de login:
Atributo | Requisito | Descrição |
---|---|---|
Action Uri | Obrigatório | Link direto para a ação (ou seja, leva à página de login do app) |
Image | Opcional: se não for fornecido, o título precisa ser fornecido |
Imagem mostrada no card Imagens com proporção de 16 x 9 e resolução de 1.264 x 712 |
Title | Opcional: se não for fornecido, a imagem precisará ser fornecida | Título do card |
Action Text | Opcional | Texto mostrado no CTA (por exemplo, "Fazer login") |
Subtitle | Opcional | Subtítulo opcional do card |
Kotlin
var SIGN_IN_CARD_ENTITY = SignInCardEntity.Builder() .addPosterImage( Image.Builder() .setImageUri(Uri.parse("http://www.x.com/image.png")) .setImageHeightInPixel(500) .setImageWidthInPixel(500) .build()) .setActionText("Sign In") .setActionUri(Uri.parse("http://xx.com/signin")) .build() client.publishUserAccountManagementRequest( PublishUserAccountManagementRequest.Builder() .setSignInCardEntity(SIGN_IN_CARD_ENTITY) .build());
Java
SignInCardEntity SIGN_IN_CARD_ENTITY = new SignInCardEntity.Builder() .addPosterImage( new Image.Builder() .setImageUri(Uri.parse("http://www.x.com/image.png")) .setImageHeightInPixel(500) .setImageWidthInPixel(500) .build()) .setActionText("Sign In") .setActionUri(Uri.parse("http://xx.com/signin")) .build(); client.publishUserAccountManagementRequest( new PublishUserAccountManagementRequest.Builder() .setSignInCardEntity(SIGN_IN_CARD_ENTITY) .build());
Quando o serviço recebe o pedido, as seguintes ações ocorrem em uma transação:
- Os dados do
UserAccountManagementCluster
do parceiro do desenvolvedor são removidos. - Os dados do pedido são analisados e armazenados no cluster UserAccountManagementCluster atualizado.
Em caso de erro, a solicitação inteira é rejeitada e o estado atual é mantido.
updatePublishStatus
Se, por qualquer motivo interno, nenhum dos clusters for publicado, é altamente recomendável atualizar o status de publicação usando a API updatePublishStatus. Isso é importante pelos seguintes motivos:
- Informar o status em todos os casos possíveis, mesmo quando o conteúdo é publicado (STATUS == PUBLISHED), é fundamental para preencher painéis que usam o status explícito para transmitir informações de integridade e outras métricas da integração.
- Se nenhum conteúdo for publicado, mas o status da integração não estiver corrompido (STATUS == NOT_PUBLISHED), o Google poderá evitar o acionamento de alertas nos painéis de integridade do app. Isso confirma que o conteúdo não foi publicado devido a uma situação esperada pelo provedor.
- Ajuda os desenvolvedores a oferecer insights sobre quando os dados foram publicados ou não.
- O Google pode usar os códigos de status para incentivar o usuário a executar ações específicas no app, como acessar o conteúdo ou resolver o problema.
Lista de códigos de status de publicação que podem ser usados:
// Content is published
AppEngagePublishStatusCode.PUBLISHED,
// Content is not published as user is not signed in
AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN,
// Content is not published as user is not subscribed
AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SUBSCRIPTION,
// Content is not published as user location is ineligible
AppEngagePublishStatusCode.NOT_PUBLISHED_INELIGIBLE_LOCATION,
// Content is not published as there is no eligible content
AppEngagePublishStatusCode.NOT_PUBLISHED_NO_ELIGIBLE_CONTENT,
// Content is not published as the feature is disabled by the client
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_FEATURE_DISABLED_BY_CLIENT,
// Content is not published as the feature due to a client error
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_CLIENT_ERROR,
// Content is not published as the feature due to a service error
// Available in v1.3.1
AppEngagePublishStatusCode.NOT_PUBLISHED_SERVICE_ERROR,
// Content is not published due to some other reason
// Reach out to engage-developers@ before using this enum.
AppEngagePublishStatusCode.NOT_PUBLISHED_OTHER
Se o conteúdo não for publicado porque o usuário não estava conectado, o Google recomenda publicar o card de login. Se, por algum motivo, os provedores não conseguirem publicar o card de login, recomendamos chamar a API updatePublishStatus usando o código de status NOT_PUBLISHED_REQUIRES_SIGN_IN.
Kotlin
client.updatePublishStatus( PublishStatusRequest.Builder() .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN) .build())
Java
client.updatePublishStatus( new PublishStatusRequest.Builder() .setStatusCode(AppEngagePublishStatusCode.NOT_PUBLISHED_REQUIRES_SIGN_IN) .build());
deleteRecommendationClusters
Essa API é usada para excluir o conteúdo dos clusters de recomendação.
Kotlin
client.deleteRecommendationClusters()
Java
client.deleteRecommendationClusters();
Quando o serviço recebe o pedido, ele remove os dados atuais dos clusters de recomendação. Em caso de erro, a solicitação inteira é rejeitada e o estado atual é mantido.
deleteFeaturedCluster
Essa API é usada para excluir o conteúdo do cluster de destaque.
Kotlin
client.deleteFeaturedCluster()
Java
client.deleteFeaturedCluster();
Quando o serviço recebe o pedido, ele remove os dados atuais do cluster de destaque. Em caso de erro, a solicitação inteira é rejeitada e o estado atual é mantido.
deleteContinuationCluster
Essa API é usada para excluir o conteúdo do cluster de continuação.
Kotlin
client.deleteContinuationCluster()
Java
client.deleteContinuationCluster();
Quando o serviço recebe o pedido, ele remove os dados atuais do cluster de continuação. Em caso de erro, a solicitação inteira é rejeitada e o estado atual é mantido.
deleteUserManagementCluster
Essa API é usada para excluir o conteúdo do cluster UserAccountManagement.
Kotlin
client.deleteUserManagementCluster()
Java
client.deleteUserManagementCluster();
Quando o serviço recebe o pedido, ele remove os dados atuais do cluster UserAccountManagement. Em caso de erro, a solicitação inteira é rejeitada e o estado atual é mantido.
deleteClusters
Essa API é usada para excluir o conteúdo de determinado tipo de cluster.
Kotlin
client.deleteClusters( DeleteClustersRequest.Builder() .addClusterType(ClusterType.TYPE_CONTINUATION) .addClusterType(ClusterType.TYPE_FEATURED) .addClusterType(ClusterType.TYPE_RECOMMENDATION) .build())
Java
client.deleteClusters( new DeleteClustersRequest.Builder() .addClusterType(ClusterType.TYPE_CONTINUATION) .addClusterType(ClusterType.TYPE_FEATURED) .addClusterType(ClusterType.TYPE_RECOMMENDATION) .build());
Quando o serviço recebe a solicitação, ele remove os dados de todos os clusters que correspondem aos tipos especificados. Os clientes podem transmitir um ou vários tipos de clusters. Em caso de erro, a solicitação inteira é rejeitada e o estado existente é mantido.
Tratamento de erros
É recomendável detectar o resultado da tarefa nas APIs de publicação. Com isso, uma ação de acompanhamento pode ser realizada para extrair e reenviar uma tarefa bem-sucedida.
Kotlin
client.publishRecommendationClusters( PublishRecommendationClustersRequest.Builder() .addRecommendationCluster(..) .build()) .addOnCompleteListener { task -> if (task.isSuccessful) { // do something } else { val exception = task.exception if (exception is AppEngageException) { @AppEngageErrorCode val errorCode = exception.errorCode if (errorCode == AppEngageErrorCode.SERVICE_NOT_FOUND) { // do something } } } }
Java
client.publishRecommendationClusters( new PublishRecommendationClustersRequest.Builder() .addRecommendationCluster(...) .build()) .addOnCompleteListener( task -> { if (task.isSuccessful()) { // do something } else { Exception exception = task.getException(); if (exception instanceof AppEngageException) { @AppEngageErrorCode int errorCode = ((AppEngageException) exception).getErrorCode(); if (errorCode == AppEngageErrorCode.SERVICE_NOT_FOUND) { // do something } } } });
O erro é retornado como AppEngageException
e a causa é incluída como um
código de erro.
Código do erro | Nome do erro | Observação |
---|---|---|
1 |
SERVICE_NOT_FOUND |
O serviço não está disponível no dispositivo. |
2 |
SERVICE_NOT_AVAILABLE |
O serviço está disponível no dispositivo em questão, mas não no momento da chamada (por exemplo, está desativado). |
3 |
SERVICE_CALL_EXECUTION_FAILURE |
A execução da tarefa falhou devido a problemas de linha de execução. Nesse caso, ela pode ser repetida. |
4 |
SERVICE_CALL_PERMISSION_DENIED |
O autor da chamada não tem permissão para fazer a chamada de serviço. |
5 |
SERVICE_CALL_INVALID_ARGUMENT |
A solicitação contém dados inválidos (por exemplo, tem um número de clusters maior do que o permitido). |
6 |
SERVICE_CALL_INTERNAL |
Há um erro no serviço. |
7 |
SERVICE_CALL_RESOURCE_EXHAUSTED |
A chamada de serviço é feita com muita frequência. |
Etapa 3: processar intents de transmissão
Além de fazer chamadas de API de conteúdo de publicação usando um job, também é
necessário configurar um
BroadcastReceiver
para receber
a solicitação de publicação de conteúdo.
O objetivo principal das intents de transmissão é reativar o app e forçar a sincronização de dados. As intents de transmissão não são projetadas para envio muito frequente. Elas só são acionadas quando o serviço do Engage determina que o conteúdo pode estar desatualizado (por exemplo, é de uma semana atrás). Dessa forma, há mais confiança de que o usuário poderá ter uma nova experiência de conteúdo, mesmo que o aplicativo não tenha sido executado por um longo período.
O BroadcastReceiver
precisa ser configurado de duas maneiras:
- Registre dinamicamente uma instância da classe
BroadcastReceiver
usandoContext.registerReceiver()
. Isso permite a comunicação de aplicativos que ainda estão ativos na memória.
Kotlin
class AppEngageBroadcastReceiver : BroadcastReceiver(){ // Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION broadcast // is received // Trigger featured cluster publish when PUBLISH_FEATURED broadcast is received // Trigger continuation cluster publish when PUBLISH_CONTINUATION broadcast is // received } fun registerBroadcastReceivers(context: Context){ var context = context context = context.applicationContext // Register Recommendation Cluster Publish Intent context.registerReceiver(AppEngageBroadcastReceiver(), IntentFilter(Intents.ACTION_PUBLISH_RECOMMENDATION)) // Register Featured Cluster Publish Intent context.registerReceiver(AppEngageBroadcastReceiver(), IntentFilter(Intents.ACTION_PUBLISH_FEATURED)) // Register Continuation Cluster Publish Intent context.registerReceiver(AppEngageBroadcastReceiver(), IntentFilter(Intents.ACTION_PUBLISH_CONTINUATION)) }
Java
class AppEngageBroadcastReceiver extends BroadcastReceiver { // Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION broadcast // is received // Trigger featured cluster publish when PUBLISH_FEATURED broadcast is received // Trigger continuation cluster publish when PUBLISH_CONTINUATION broadcast is // received } public static void registerBroadcastReceivers(Context context) { context = context.getApplicationContext(); // Register Recommendation Cluster Publish Intent context.registerReceiver(new AppEngageBroadcastReceiver(), new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_RECOMMENDATION)); // Register Featured Cluster Publish Intent context.registerReceiver(new AppEngageBroadcastReceiver(), new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_FEATURED)); // Register Continuation Cluster Publish Intent context.registerReceiver(new AppEngageBroadcastReceiver(), new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_CONTINUATION)); }
- Declare estaticamente uma implementação com a tag
<receiver>
no arquivoAndroidManifest.xml
. Isso permite que o aplicativo receba intents de transmissão quando não está em execução e também permite que ele publique o conteúdo.
<application>
<receiver
android:name=".AppEngageBroadcastReceiver"
android:exported="true"
android:enabled="true">
<intent-filter>
<action android:name="com.google.android.engage.action.PUBLISH_RECOMMENDATION" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.engage.action.PUBLISH_FEATURED" />
</intent-filter>
<intent-filter>
<action android:name="com.google.android.engage.action.PUBLISH_CONTINUATION" />
</intent-filter>
</receiver>
</application>
As intents abaixo são enviadas pelo serviço:
com.google.android.engage.action.PUBLISH_RECOMMENDATION
Recomendamos que você inicie uma chamadapublishRecommendationClusters
ao receber essa intent.com.google.android.engage.action.PUBLISH_FEATURED
Recomendamos que você inicie uma chamadapublishFeaturedCluster
ao receber essa intent.com.google.android.engage.action.PUBLISH_CONTINUATION
Recomendamos que você inicie uma chamadapublishContinuationCluster
ao receber essa intent.
Fluxo de trabalho de integração
Para acessar um guia explicativo sobre como verificar a integração após a conclusão, consulte Fluxo de trabalho de integração de desenvolvedor.
Perguntas frequentes
Consulte as Perguntas frequentes sobre o SDK Engage para acessar as perguntas frequentes.
Contato
Entre em contato com engagement-developers@google.com se tiver perguntas durante o processo de integração.
Próximas etapas
Depois de concluir essa integração, as próximas etapas serão as seguintes:
- Envie um e-mail para engage-developers@google.com e anexe seu APK integrado pronto para ser testado pelo Google.
- O Google realiza uma verificação e revisão interna para garantir que a integração funcione como esperado. Se for necessário fazer mudanças, o Google vai entrar em contato informando todos os detalhes necessários.
- Quando o teste estiver concluído e nenhuma mudança for necessária, o Google vai entrar em contato para informar que você pode começar a publicar o APK atualizado e integrado na Play Store.
- Depois que o Google confirmar a publicação do APK atualizado na Play Store, seus clusters de recomendação, destaque e continuação poderão ser publicados e ficar visíveis aos usuários.