Google tworzy platformę na urządzeniu, która porządkuje aplikacje użytkowników według kategorii i zapewnia nowe, atrakcyjne możliwości związane z oglądaniem i odkrywaniem treści aplikacji w spersonalizowany sposób. Dzięki temu partnerzy mogą prezentować swoje najlepsze treści na specjalnym kanale poza aplikacją.
Ten przewodnik zawiera instrukcje dla deweloperów, którzy chcą zintegrować swoje treści wideo, korzystając z pakietu SDK dla Agencji do zapełnienia zarówno tej nowej powierzchni, jak i dotychczasowych platform Google.
Szczegóły integracji
Terminologia
Ta integracja obejmuje 3 typy klastrów: Rekomendacja, Kontynuacja i Polecane.
Klastry rekomendacji wyświetlają spersonalizowane sugestie dotyczące treści od konkretnego partnera ds. deweloperów.
Rekomendacje mają taką strukturę:
Klaster rekomendacji: widok interfejsu zawierający grupę rekomendacji od tego samego partnera ds. deweloperów.
Encja: obiekt reprezentujący pojedynczy element w klastrze. Elementem może być np. film, program telewizyjny, serial telewizyjny lub wideo na żywo. Listę obsługiwanych typów encji znajdziesz w sekcji Podaj dane encji.
Klaster Kontynuacja pokazuje niedokończone filmy i odpowiednie nowo opublikowane odcinki wielu partnerów deweloperów w jednej grupie UI. Każdy deweloper będzie mógł transmitować maksymalnie 10 encji w klastrze kontynuacji. Badania pokazują, że największe zaangażowanie użytkowników największe są spersonalizowane rekomendacje i treści z sekcji Kontynuuj.
Klaster Polecane prezentuje wybrane elementy od wielu partnerów deweloperów w jednym grupowaniu UI. U góry interfejsu będzie widoczny pojedynczy klaster Polecane, miejsce docelowe nadrzędne względem wszystkich klastrów rekomendacji. Każdy partner deweloper będzie mógł rozpowszechniać w klastrze Polecane maksymalnie 10 encji.
Przygotowanie
Minimalny poziom interfejsu API: 19
Dodaj bibliotekę com.google.android.engage:engage-core
do aplikacji:
dependencies {
// Make sure you also include that repository in your project's build.gradle file.
implementation 'com.google.android.engage:engage-core:1.4.0'
}
Więcej informacji znajdziesz w artykule o widoczności pakietów w Androidzie 11.
Podsumowanie
Projekt opiera się na implementacji powiązanej usługi.
Dane, które klient może publikować, podlegają tym ograniczeniom w przypadku różnych typów klastrów:
Typ klastra | Limity klastrów | Maksymalne limity encji w klastrze |
---|---|---|
Klastry rekomendacji | Maksymalnie 5 | Maksymalnie 50 |
Klaster kontynuacji | Maksymalnie 1 | Maksymalnie 10 |
Polecany klaster | Maksymalnie 1 | Maksymalnie 10 |
Krok 0. Migracja z dotychczasowej integracji pakietu SDK Media Home
Zmapuj modele danych z istniejącej integracji
Jeśli przechodzisz z dotychczasowej integracji Media Home, w tabeli poniżej znajdziesz informacje o mapowaniu modeli danych z dotychczasowych pakietów SDK na nowy pakiet Engage SDK:
Odpowiednik integracji MediaHomeVideoContract | Odpowiednik integracji Google Workspace z pakietem SDK |
---|---|
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 |
Podzielony na osobne klasy: EventVideo , LiveStreamingVideo , Movie , TvEpisode , TvSeason , TvShow , VideoClipEntity |
com.google.android.mediahome.video.PreviewProgram.Builder |
Są podzielone na kreatory w oddzielnych klasach: EventVideo , LiveStreamingVideo , Movie , TvEpisode , TvSeason , TvShow , VideoClipEntity |
com.google.android.mediahome.video.VideoContract |
Już nie potrzebuję tej usługi. |
com.google.android.mediahome.video.WatchNextProgram |
Podzielony na atrybuty w osobnych klasach: EventVideoEntity , LiveStreamingVideoEntity , MovieEntity , TvEpisodeEntity , TvSeasonEntity , TvShowEntity , VideoClipEntity |
com.google.android.mediahome.video.WatchNextProgram.Builder |
Podzielony na atrybuty w osobnych klasach: EventVideoEntity , LiveStreamingVideoEntity , MovieEntity , TvEpisodeEntity , TvSeasonEntity , TvShowEntity , VideoClipEntity |
Publikowanie klastrów w pakiecie Media Home SDK a pakiet SDK dla Agencji
Za pomocą pakietu Media Home SDK klastry i elementy były publikowane przy użyciu osobnych interfejsów API:
// 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());
Dzięki pakietowi SDK dla Agencji publikowanie klastrów i encji jest łączone w jedno wywołanie interfejsu API. Wszystkie encje należące do klastra są publikowane razem z tym klastrem:
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();
Krok 1. Podaj dane encji
Pakiet SDK ma zdefiniowane różne elementy reprezentujące każdy typ elementu. W przypadku kategorii Zegarki obsługujemy:
W tabeli poniżej opisujemy atrybuty i wymagania dla poszczególnych typów.
MovieEntity
Atrybut | Wymóg | Uwagi |
---|---|---|
Nazwa | Wymagany | |
Obrazy plakatu | Wymagany | Wymagany jest co najmniej 1 obraz o współczynniku proporcji. (Preferowana jest orientacja pozioma, ale w zależności od sytuacji zalecamy przesyłanie zarówno obrazów pionowych, jak i poziomych).
Wskazówki znajdziesz w specyfikacji obrazów. |
Identyfikator URI odtwarzania | Wymagany |
Precyzyjny link do aplikacji dostawcy, aby rozpocząć odtwarzanie filmu. Uwaga: do atrybucji możesz używać precyzyjnych linków. Przeczytaj te najczęstsze pytania |
Identyfikator URI strony z informacjami | Opcjonalnie |
Precyzyjny link do aplikacji dostawcy, który pozwala wyświetlić szczegółowe informacje o filmie. Uwaga: do atrybucji możesz używać precyzyjnych linków. Przeczytaj te najczęstsze pytania |
Data premiery | Wymagany | W milisekundach w epoce. |
Dostępność | Wymagany | AVAILABLE: treść jest dostępna dla użytkownika bez wykonywania dalszych czynności. FREE_WITH_SUBSCRIPTION: treści są dostępne po wykupieniu subskrypcji przez użytkownika. PAID_CONTENT: treści wymagają zakupu lub wypożyczenia przez użytkownika. KUPIONE: treść została kupiona lub wypożyczona przez użytkownika. |
Cena oferty | Opcjonalnie | Dowolny tekst |
Czas działania | Wymagany | W milisekundach. |
Gatunek | Wymagany | Dowolny tekst |
Oceny treści | Wymagany | Tekst dowolny, zgodny ze standardem branżowym. (Przykład) |
Typ „Warte obejrzenia” | Wymagane warunkowo | Musisz podać go, gdy element znajduje się w klastrze kontynuacji i musi być jednym z tych 4 typów: KONTYNUUJ: użytkownik obejrzał już ponad 1 minutę tych treści. NOWOŚĆ: użytkownik obejrzał wszystkie dostępne odcinki niektórych odcinków, ale pojawił się nowy odcinek i jest tylko jeden nieobejrzany odcinek. Dotyczy to m.in. programów telewizyjnych, nagranych meczów piłki nożnej w jednym serialu. DALEJ: użytkownik obejrzał co najmniej 1 pełny odcinek niektórych treści w postaci odcinków, ale pozostał dokładnie 1 odcinek lub pozostał dokładnie 1 odcinek, w którym ostatni odcinek nie jest „NOWY”. Został on opublikowany, zanim użytkownik zaczął oglądać treści w formie odcinków. LISTA DO obejrzenia: użytkownik jednoznacznie chce dodać film, wydarzenie lub serial do listy Do obejrzenia, aby ręcznie wybrać, co chce obejrzeć w następnej kolejności. |
Czas ostatniego zaangażowania | Wymagane warunkowo | Należy je podać, gdy element znajduje się w klastrze kontynuacji. W milisekundach epoki. |
Czas ostatniej pozycji odtwarzania | Wymagane warunkowo | Należy podać je, gdy element znajduje się w klastrze kontynuacyjnym, a element WatchNextType ma wartość Continue. W milisekundach w epoce. |
TvShowEntity
Atrybut | Wymóg | Uwagi |
---|---|---|
Nazwa | Wymagany | |
Obrazy plakatu | Wymagany | Wymagany jest co najmniej 1 obraz o współczynniku proporcji. (Preferowana jest orientacja pozioma, ale w zależności od sytuacji zalecamy przesyłanie zarówno obrazów pionowych, jak i poziomych).
Wskazówki znajdziesz w specyfikacji obrazów. |
Identyfikator URI strony z informacjami | Wymagany |
Precyzyjny link do aplikacji dostawcy, który pozwala wyświetlić szczegóły programu telewizyjnego. Uwaga: do atrybucji możesz używać precyzyjnych linków. Przeczytaj te najczęstsze pytania |
Identyfikator URI odtwarzania | Opcjonalnie |
Precyzyjny link do aplikacji dostawcy, aby rozpocząć odtwarzanie programu telewizyjnego. Uwaga: do atrybucji możesz używać precyzyjnych linków. Przeczytaj te najczęstsze pytania |
Data emisji pierwszego odcinka | Wymagany | W milisekundach w epoce. |
Data najnowszego odcinka | Opcjonalnie | W milisekundach w epoce. |
Dostępność | Wymagany | AVAILABLE: treść jest dostępna dla użytkownika bez wykonywania dalszych czynności. FREE_WITH_SUBSCRIPTION: treści są dostępne po wykupieniu subskrypcji przez użytkownika. PAID_CONTENT: treści wymagają zakupu lub wypożyczenia przez użytkownika. KUPIONE: treść została kupiona lub wypożyczona przez użytkownika. |
Cena oferty | Opcjonalnie | Dowolny tekst |
Liczba sezonów | Wymagany | Dodatnia liczba całkowita |
Gatunek | Wymagany | Dowolny tekst |
Oceny treści | Wymagany | Tekst dowolny, zgodny ze standardem branżowym. (Przykład) |
Typ „Warte obejrzenia” | Wymagane warunkowo | Musisz podać go, gdy element znajduje się w klastrze kontynuacji i musi być jednym z tych 4 typów: KONTYNUUJ: użytkownik obejrzał już ponad 1 minutę tych treści. NOWOŚĆ: użytkownik obejrzał wszystkie dostępne odcinki niektórych odcinków, ale pojawił się nowy odcinek i jest tylko jeden nieobejrzany odcinek. Dotyczy to m.in. programów telewizyjnych, nagranych meczów piłki nożnej w jednym serialu. DALEJ: użytkownik obejrzał co najmniej 1 pełny odcinek niektórych treści w postaci odcinków, ale pozostał dokładnie 1 odcinek lub pozostał dokładnie 1 odcinek, w którym ostatni odcinek nie jest „NOWY”. Został on opublikowany, zanim użytkownik zaczął oglądać treści w formie odcinków. LISTA DO obejrzenia: użytkownik jednoznacznie chce dodać film, wydarzenie lub serial do listy Do obejrzenia, aby ręcznie wybrać, co chce obejrzeć w następnej kolejności. |
Czas ostatniego zaangażowania | Wymagane warunkowo | Należy je podać, gdy element znajduje się w klastrze kontynuacji. W milisekundach epoki. |
Czas ostatniej pozycji odtwarzania | Wymagane warunkowo | Należy podać je, gdy element znajduje się w klastrze kontynuacyjnym, a element WatchNextType ma wartość Continue. W milisekundach w epoce. |
TvSeasonEntity
Atrybut | Wymóg | Uwagi |
---|---|---|
Nazwa | Wymagany | |
Obrazy plakatu | Wymagany | Wymagany jest co najmniej 1 obraz o współczynniku proporcji. (Preferowana jest orientacja pozioma, ale w zależności od sytuacji zalecamy przesyłanie zarówno obrazów pionowych, jak i poziomych).
Wskazówki znajdziesz w specyfikacji obrazów. |
Identyfikator URI strony z informacjami | Wymagany |
Precyzyjny link do aplikacji dostawcy umożliwiającej wyświetlenie szczegółów sezonu programu telewizyjnego. Uwaga: do atrybucji możesz używać precyzyjnych linków. Przeczytaj te najczęstsze pytania |
Identyfikator URI odtwarzania | Opcjonalnie |
Precyzyjny link do aplikacji dostawcy umożliwiającej rozpoczęcie oglądania sezonu programu telewizyjnego. Uwaga: do atrybucji możesz używać precyzyjnych linków. Przeczytaj te najczęstsze pytania |
Wyświetl numer sezonu |
Opcjonalny Dostępne w wersji 1.3.1 |
Ciąg znaków |
Data emisji pierwszego odcinka | Wymagany | W milisekundach w epoce. |
Data najnowszego odcinka | Opcjonalnie | W milisekundach w epoce. |
Dostępność | Wymagany | AVAILABLE: treść jest dostępna dla użytkownika bez wykonywania dalszych czynności. FREE_WITH_SUBSCRIPTION: treści są dostępne po wykupieniu subskrypcji przez użytkownika. PAID_CONTENT: treści wymagają zakupu lub wypożyczenia przez użytkownika. KUPIONE: treść została kupiona lub wypożyczona przez użytkownika. |
Cena oferty | Opcjonalnie | Dowolny tekst |
Liczba odcinków | Wymagany | Dodatnia liczba całkowita |
Gatunek | Wymagany | Dowolny tekst |
Oceny treści | Wymagany | Tekst dowolny, zgodny ze standardem branżowym. (Przykład) |
Typ „Warte obejrzenia” | Wymagane warunkowo | Musisz podać go, gdy element znajduje się w klastrze kontynuacji i musi być jednym z tych 4 typów: KONTYNUUJ: użytkownik obejrzał już ponad 1 minutę tych treści. NOWOŚĆ: użytkownik obejrzał wszystkie dostępne odcinki niektórych odcinków, ale pojawił się nowy odcinek i jest tylko jeden nieobejrzany odcinek. Dotyczy to m.in. programów telewizyjnych, nagranych meczów piłki nożnej w jednym serialu. DALEJ: użytkownik obejrzał co najmniej 1 pełny odcinek niektórych treści w postaci odcinków, ale pozostał dokładnie 1 odcinek lub pozostał dokładnie 1 odcinek, w którym ostatni odcinek nie jest „NOWY”. Został on opublikowany, zanim użytkownik zaczął oglądać treści w formie odcinków. LISTA DO obejrzenia: użytkownik jednoznacznie chce dodać film, wydarzenie lub serial do listy Do obejrzenia, aby ręcznie wybrać, co chce obejrzeć w następnej kolejności. |
Czas ostatniego zaangażowania | Wymagane warunkowo | Należy je podać, gdy element znajduje się w klastrze kontynuacji. W milisekundach epoki. |
Czas ostatniej pozycji odtwarzania | Wymagane warunkowo | Należy podać je, gdy element znajduje się w klastrze kontynuacyjnym, a element WatchNextType ma wartość Continue. W milisekundach w epoce. |
TvEpisodeEntity
Atrybut | Wymóg | Uwagi |
---|---|---|
Nazwa | Wymagany | |
Obrazy plakatu | Wymagany | Wymagany jest co najmniej 1 obraz o współczynniku proporcji. (Preferowana jest orientacja pozioma, ale w zależności od sytuacji zalecamy przesyłanie zarówno obrazów pionowych, jak i poziomych).
Wskazówki znajdziesz w specyfikacji obrazów. |
Identyfikator URI odtwarzania | Wymagany |
Precyzyjny link do aplikacji dostawcy, aby rozpocząć odtwarzanie odcinka. Uwaga: do atrybucji możesz używać precyzyjnych linków. Przeczytaj te najczęstsze pytania |
Identyfikator URI strony z informacjami | Opcjonalnie |
Precyzyjny link do aplikacji dostawcy, który pozwala wyświetlić szczegóły odcinka programu telewizyjnego. Uwaga: do atrybucji możesz używać precyzyjnych linków. Przeczytaj te najczęstsze pytania |
Wyświetl numer odcinka |
Opcjonalny Dostępne w wersji 1.3.1 |
Ciąg znaków |
Data emisji | Wymagany | W milisekundach w epoce. |
Dostępność | Wymagany | AVAILABLE: treść jest dostępna dla użytkownika bez wykonywania dalszych czynności. FREE_WITH_SUBSCRIPTION: treści są dostępne po wykupieniu subskrypcji przez użytkownika. PAID_CONTENT: treści wymagają zakupu lub wypożyczenia przez użytkownika. KUPIONE: treść została kupiona lub wypożyczona przez użytkownika. |
Cena oferty | Opcjonalnie | Dowolny tekst |
Czas działania | Wymagany | Musi być wartością dodatnią w milisekundach. |
Gatunek | Wymagany | Dowolny tekst |
Oceny treści | Wymagany | Tekst dowolny, zgodny ze standardem branżowym. (Przykład) |
Typ „Warte obejrzenia” | Wymagane warunkowo | Musisz podać go, gdy element znajduje się w klastrze kontynuacji i musi być jednym z tych 4 typów: KONTYNUUJ: użytkownik obejrzał już ponad 1 minutę tych treści. NOWOŚĆ: użytkownik obejrzał wszystkie dostępne odcinki niektórych odcinków, ale pojawił się nowy odcinek i jest tylko jeden nieobejrzany odcinek. Dotyczy to m.in. programów telewizyjnych, nagranych meczów piłki nożnej w jednym serialu. DALEJ: użytkownik obejrzał co najmniej 1 pełny odcinek niektórych treści w postaci odcinków, ale pozostał dokładnie 1 odcinek lub pozostał dokładnie 1 odcinek, w którym ostatni odcinek nie jest „NOWY”. Został on opublikowany, zanim użytkownik zaczął oglądać treści w formie odcinków. LISTA DO obejrzenia: użytkownik jednoznacznie chce dodać film, wydarzenie lub serial do listy Do obejrzenia, aby ręcznie wybrać, co chce obejrzeć w następnej kolejności. |
Czas ostatniego zaangażowania | Wymagane warunkowo | Należy je podać, gdy element znajduje się w klastrze kontynuacji. W milisekundach epoki. |
Czas ostatniej pozycji odtwarzania | Wymagane warunkowo | Należy podać je, gdy element znajduje się w klastrze kontynuacyjnym, a element WatchNextType ma wartość Continue. W milisekundach w epoce. |
LiveStreamingVideoEntity
Atrybut | Wymóg | Uwagi |
---|---|---|
Nazwa | Wymagany | |
Obrazy plakatu | Wymagany | Wymagany jest co najmniej 1 obraz o współczynniku proporcji. (Preferowana jest orientacja pozioma, ale w zależności od sytuacji zalecamy przesyłanie zarówno obrazów pionowych, jak i poziomych).
Wskazówki znajdziesz w specyfikacji obrazów. |
Identyfikator URI odtwarzania | Wymagany |
Precyzyjny link do aplikacji dostawcy, aby rozpocząć odtwarzanie filmu. Uwaga: do atrybucji możesz używać precyzyjnych linków. Przeczytaj te najczęstsze pytania |
Prezenterzy | Wymagany | Dowolny tekst |
Godzina rozpoczęcia | Opcjonalnie | W milisekundach w epoce. |
Godzina zakończenia | Opcjonalnie | W milisekundach w epoce. |
liczbę wyświetleń; | Opcjonalnie | Tekst dowolny, musi być zlokalizowany. |
Typ „Warte obejrzenia” | Wymagane warunkowo | Musisz podać go, gdy element znajduje się w klastrze kontynuacji i musi być jednym z tych 4 typów: KONTYNUUJ: użytkownik obejrzał już ponad 1 minutę tych treści. NOWOŚĆ: użytkownik obejrzał wszystkie dostępne odcinki niektórych odcinków, ale pojawił się nowy odcinek i jest tylko jeden nieobejrzany odcinek. Dotyczy to m.in. programów telewizyjnych, nagranych meczów piłki nożnej w jednym serialu. DALEJ: użytkownik obejrzał co najmniej 1 pełny odcinek niektórych treści w postaci odcinków, ale pozostał dokładnie 1 odcinek lub pozostał dokładnie 1 odcinek, w którym ostatni odcinek nie jest „NOWY”. Został on opublikowany, zanim użytkownik zaczął oglądać treści w formie odcinków. LISTA DO obejrzenia: użytkownik jednoznacznie chce dodać film, wydarzenie lub serial do listy Do obejrzenia, aby ręcznie wybrać, co chce obejrzeć w następnej kolejności. |
Czas ostatniego zaangażowania | Wymagane warunkowo | Należy je podać, gdy element znajduje się w klastrze kontynuacji. W milisekundach epoki. |
Czas ostatniej pozycji odtwarzania | Wymagane warunkowo | Należy podać je, gdy element znajduje się w klastrze kontynuacyjnym, a element WatchNextType ma wartość Continue. W milisekundach w epoce. |
VideoClipEntity
Obiekt VideoClipEntity
reprezentuje film pochodzący z mediów społecznościowych takich jak TikTok czy YouTube.
Atrybut | Wymóg | Uwagi |
---|---|---|
Nazwa | Wymagany | |
Obrazy plakatu | Wymagany | Wymagany jest co najmniej 1 obraz o współczynniku proporcji. (Preferowana jest orientacja pozioma, ale w zależności od sytuacji zalecamy przesyłanie zarówno obrazów pionowych, jak i poziomych).
Wskazówki znajdziesz w specyfikacji obrazów. |
Identyfikator URI odtwarzania | Wymagany |
Precyzyjny link do aplikacji dostawcy, aby rozpocząć odtwarzanie filmu. Uwaga: do atrybucji możesz używać precyzyjnych linków. Przeczytaj te najczęstsze pytania |
datę utworzenia; | Wymagany | W milisekundach w epoce. |
Czas działania | Wymagany | Musi być wartością dodatnią w milisekundach. |
Twórca | Wymagany | Dowolny tekst |
Obraz twórcy | Opcjonalnie | Obraz awatara twórcy |
liczbę wyświetleń; | Opcjonalnie | Tekst dowolny, musi być zlokalizowany. |
Typ „Warte obejrzenia” | Wymagane warunkowo | Musisz podać go, gdy element znajduje się w klastrze kontynuacji i musi być jednym z tych 4 typów: KONTYNUUJ: użytkownik obejrzał już ponad 1 minutę tych treści. NOWOŚĆ: użytkownik obejrzał wszystkie dostępne odcinki niektórych odcinków, ale pojawił się nowy odcinek i jest tylko jeden nieobejrzany odcinek. Dotyczy to m.in. programów telewizyjnych, nagranych meczów piłki nożnej w jednym serialu. DALEJ: użytkownik obejrzał co najmniej 1 pełny odcinek niektórych treści w postaci odcinków, ale pozostał dokładnie 1 odcinek lub pozostał dokładnie 1 odcinek, w którym ostatni odcinek nie jest „NOWY”. Został on opublikowany, zanim użytkownik zaczął oglądać treści w formie odcinków. LISTA DO obejrzenia: użytkownik jednoznacznie chce dodać film, wydarzenie lub serial do listy Do obejrzenia, aby ręcznie wybrać, co chce obejrzeć w następnej kolejności. |
Czas ostatniego zaangażowania | Wymagane warunkowo | Należy je podać, gdy element znajduje się w klastrze kontynuacji. W milisekundach epoki. |
Czas ostatniej pozycji odtwarzania | Wymagane warunkowo | Należy podać je, gdy element znajduje się w klastrze kontynuacyjnym, a element WatchNextType ma wartość Continue. W milisekundach w epoce. |
Specyfikacja obrazu
W tej sekcji znajdziesz listę wymagań dotyczących komponentów z obrazem:
Formaty plików
PNG, JPG, statyczne pliki GIF, WebP
Maksymalny rozmiar pliku
5120 KB
Dodatkowe zalecenia
- Bezpieczny obszar obrazu: ważne treści umieść w środkowych 80% obrazu.
Przykład
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();
Krok 2. Podaj dane klastra
Zalecamy, aby zadanie publikowania treści było wykonywane w tle (np. za pomocą narzędzia WorkManager) i planowane regularnie lub na podstawie zdarzeń (np. za każdym razem, gdy użytkownik otworzy aplikację lub gdy tylko doda coś do koszyka).
Za publikowanie klastrów odpowiada AppEngagePublishClient
. Klient udostępnia te interfejsy API:
isServiceAvailable
publishRecommendationClusters
publishFeaturedCluster
publishContinuationCluster
publishUserAccountManagementRequest
updatePublishStatus
deleteRecommendationsClusters
deleteFeaturedCluster
deleteContinuationCluster
deleteUserManagementCluster
deleteClusters
isServiceAvailable
Ten interfejs API służy do sprawdzania, czy usługa jest dostępna do integracji i czy treści można zaprezentować na urządzeniu.
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
Ten interfejs API służy do publikowania listy obiektów 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());
Gdy usługa otrzyma żądanie, w ramach jednej transakcji wykonywane są te działania:
- Dotychczasowe dane aplikacji
RecommendationCluster
od partnera dewelopera zostaną usunięte. - Dane z żądania są analizowane i przechowywane w zaktualizowanym klastrze rekomendacji.
W przypadku błędu całe żądanie jest odrzucane, a istniejący stan zostaje zachowany.
publishFeaturedCluster
Ten interfejs API służy do publikowania listy obiektów 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());
Gdy usługa otrzyma żądanie, w ramach jednej transakcji wykonywane są te działania:
- Dotychczasowe dane aplikacji
FeaturedCluster
od partnera dewelopera zostaną usunięte. - Dane z żądania są analizowane i przechowywane w zaktualizowanym klastrze Polecane.
W przypadku błędu całe żądanie jest odrzucane, a istniejący stan zostaje zachowany.
publishContinuationCluster
Ten interfejs API służy do publikowania obiektu 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());
Gdy usługa otrzyma żądanie, w ramach jednej transakcji wykonywane są te działania:
- Dotychczasowe dane aplikacji
ContinuationCluster
od partnera dewelopera zostaną usunięte. - Dane z żądania są analizowane i przechowywane w zaktualizowanym klastrze kontynuacji.
W przypadku błędu całe żądanie jest odrzucane, a istniejący stan zostaje zachowany.
publishUserAccountManagementRequest
Ten interfejs API służy do publikowania karty logowania . Użytkownicy są kierowani na stronę logowania w aplikacji, na której mogą publikować treści (lub udostępniać im bardziej spersonalizowane treści).
Te metadane są częścią karty logowania –
Atrybut | Wymóg | Opis |
---|---|---|
Identyfikator URI działania | Wymagane | Precyzyjny link do działania (np. do strony logowania w aplikacji) |
Obraz | Opcjonalnie – jeśli nie podano tytułu, należy podać tytuł |
Obraz widoczny na karcie obrazy o współczynniku proporcji 16 x 9 i rozdzielczości 1264 x 712, |
tytuł; | Opcjonalnie – jeśli nie podano, należy przesłać obraz. | Tytuł na karcie |
Tekst działania | Opcjonalnie | Tekst wyświetlany w wezwaniu do działania (np. „Zaloguj się”) |
Podtytuł | Opcjonalnie | Opcjonalne napisy na karcie |
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());
Gdy usługa otrzyma żądanie, w ramach jednej transakcji wykonywane są te działania:
- Dotychczasowe dane
UserAccountManagementCluster
od partnera dewelopera zostaną usunięte. - Dane z żądania są analizowane i przechowywane w zaktualizowanym klastrze UserAccountManagementCluster.
W przypadku błędu całe żądanie jest odrzucane, a istniejący stan zostaje zachowany.
updatePublishStatus
Jeśli z jakichkolwiek wewnętrznych powodów biznesowych nie zostanie opublikowany żaden z klastrów, zdecydowanie zalecamy zaktualizowanie stanu publikacji za pomocą interfejsu API updatePublishStatus. To ważne, ponieważ :
- Podanie stanu we wszystkich scenariuszach, nawet po opublikowaniu treści (STAN == OPUBLIKOWANO), ma kluczowe znaczenie przy wypełnianiu paneli, które korzystają z tego jednoznacznego stanu do przekazywania informacji o stanie i innych wskaźnikach integracji.
- Jeśli treści nie są opublikowane, ale stan integracji nie jest uszkodzony (STATUS == NOT_OpublikujED), Google może uniknąć aktywowania alertów w panelach stanu aplikacji. Jest to potwierdzenie, że treści nie zostały opublikowane z powodu oczekiwanej sytuacji z punktu widzenia dostawcy.
- Dzięki temu deweloperzy mogą określić, kiedy dane są publikowane, a kiedy nie.
- Google może używać kodów stanu, aby skłonić użytkownika do wykonania określonych działań w aplikacji, co pozwoli mu zobaczyć zawartość aplikacji lub ją przezwyciężyć.
Lista kodów stanu kwalifikującego się do publikacji :
// 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
Jeśli treści nie zostały opublikowane, ponieważ użytkownik nie jest zalogowany, zalecamy opublikowanie karty logowania. Jeśli z jakiegoś powodu dostawcy nie mogą opublikować karty logowania, zalecamy wywołanie interfejsu API updatePublishStatus z kodem stanu NOT_OpublikujED_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
Ten interfejs API służy do usuwania zawartości klastrów rekomendacji.
Kotlin
client.deleteRecommendationClusters()
Java
client.deleteRecommendationClusters();
Gdy usługa otrzyma żądanie, usunie istniejące dane z klastrów rekomendacji. W przypadku błędu całe żądanie jest odrzucane, a obecny stan zostaje zachowany.
deleteFeaturedCluster
Ten interfejs API służy do usuwania zawartości polecanego klastra.
Kotlin
client.deleteFeaturedCluster()
Java
client.deleteFeaturedCluster();
Po otrzymaniu żądania usługa usuwa istniejące dane z polecanego klastra. W przypadku błędu całe żądanie jest odrzucane, a obecny stan zostaje zachowany.
deleteContinuationCluster
Ten interfejs API służy do usuwania zawartości klastra kontynuacji.
Kotlin
client.deleteContinuationCluster()
Java
client.deleteContinuationCluster();
Gdy usługa otrzyma żądanie, usunie istniejące dane z klastra kontynuacji. W przypadku błędu całe żądanie jest odrzucane, a obecny stan zostaje zachowany.
deleteUserManagementCluster
Ten interfejs API służy do usuwania zawartości klastra UserAccountManagement.
Kotlin
client.deleteUserManagementCluster()
Java
client.deleteUserManagementCluster();
Po otrzymaniu żądania usługa usuwa istniejące dane z klastra UserAccountManagement. W przypadku błędu całe żądanie jest odrzucane, a bieżący stan zostaje zachowany.
deleteClusters
Ten interfejs API służy do usuwania treści określonego typu klastra.
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());
Gdy usługa otrzymuje żądanie, usuwa istniejące dane ze wszystkich klastrów pasujących do określonych typów klastrów. Klienty mogą przekazywać 1 lub wiele typów klastrów. W przypadku błędu całe żądanie jest odrzucane, a obecny stan zostaje zachowany.
Obsługa błędów
Zdecydowanie zalecamy wsłuchiwanie się w wynik zadania z interfejsów API publikowania, aby można było podjąć dalsze działania w celu odzyskania udanego zadania i ponownego przesłania go.
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 } } } });
Błąd jest zwracany jako AppEngageException
, a przyczyna jest podana w postaci kodu błędu.
Kod błędu | Uwaga |
---|---|
SERVICE_NOT_FOUND |
Usługa jest niedostępna na danym urządzeniu. |
SERVICE_NOT_AVAILABLE |
Usługa jest dostępna na danym urządzeniu, ale nie jest dostępna w momencie połączenia (na przykład jest wyraźnie wyłączona). |
SERVICE_CALL_EXECUTION_FAILURE |
Nie udało się wykonać zadania z powodu problemów z wątkiem. W takim przypadku można spróbować ponownie. |
SERVICE_CALL_PERMISSION_DENIED |
Rozmówca nie może nawiązać połączenia z usługą. |
SERVICE_CALL_INVALID_ARGUMENT |
Żądanie zawiera nieprawidłowe dane (na przykład więcej niż dozwolona liczba klastrów). |
SERVICE_CALL_INTERNAL |
Po stronie usługi wystąpił błąd. |
SERVICE_CALL_RESOURCE_EXHAUSTED |
Wywoływanie usługi jest wykonywane zbyt często. |
Krok 3. Obsługuj intencje transmisji
Oprócz wykonywania wywołań interfejsu Content API w zadaniu musisz też skonfigurować BroadcastReceiver
, aby odbierać żądanie opublikowania treści.
Intencje dotyczące przesyłania służą głównie do reaktywacji aplikacji i wymuszania synchronizacji danych. Intencje transmisji nie są przeznaczone do wysyłania zbyt często. Jest wywoływane tylko wtedy, gdy usługa dla Agencji stwierdzi, że treści mogą być nieaktualne (np. sprzed tygodnia). Dzięki temu zyska on większą pewność, że użytkownik będzie mógł korzystać z nowych treści, nawet jeśli aplikacja nie była uruchamiana od dłuższego czasu.
BroadcastReceiver
należy skonfigurować na dwa sposoby:
- Dynamicznie zarejestruj instancję klasy
BroadcastReceiver
za pomocąContext.registerReceiver()
. Umożliwia to komunikację z aplikacji, które wciąż są zapisane w pamięci.
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)); }
- Statycznie zadeklaruj implementację za pomocą tagu
<receiver>
w plikuAndroidManifest.xml
. Dzięki temu aplikacja może odbierać komunikaty, gdy nie jest uruchomiona, oraz publikować treści.
<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>
Usługa wysyła te zamiary:
com.google.android.engage.action.PUBLISH_RECOMMENDATION
Zalecamy uruchomienie wywołaniapublishRecommendationClusters
przy odbieraniu tej intencji.com.google.android.engage.action.PUBLISH_FEATURED
Zalecamy uruchomienie wywołaniapublishFeaturedCluster
po otrzymaniu tej intencji.com.google.android.engage.action.PUBLISH_CONTINUATION
Gdy odbierasz tę intencję, zalecamy uruchomienie wywołaniapublishContinuationCluster
.
Przepływ pracy w integracji
Szczegółowy przewodnik dotyczący weryfikowania integracji po jej zakończeniu znajdziesz w artykule o procesie integracji programistycznej Google Workspace.
Najczęstsze pytania
Zapoznaj się z odpowiedziami na najczęstsze pytania dotyczące pakietu SDK dla Agencji.
Kontakt
Jeśli masz pytania dotyczące procesu integracji, wyślij e-maila na adres engagement-developers@google.com.
Dalsze kroki
Po zakończeniu integracji wykonaj te czynności:
- Wyślij e-maila na adres Engage-developers@google.com i załącz zintegrowany pakiet APK, który jest gotowy do przetestowania przez Google.
- Google przeprowadza weryfikację i weryfikację wewnętrzną, aby mieć pewność, że integracja działa zgodnie z oczekiwaniami. Jeśli potrzebne będą zmiany, Google skontaktuje się z Tobą, aby przekazać Ci niezbędne informacje.
- Gdy testy zostaną ukończone i nie będą wymagane żadne zmiany, Google skontaktuje się z Tobą, aby powiadomić Cię, że możesz rozpocząć publikowanie zaktualizowanego i zintegrowanego pakietu APK w Sklepie Play.
- Gdy Google potwierdzi, że zaktualizowany plik APK został opublikowany w Sklepie Play, klastry Rekomendacja, Polecane i Kontynuacja mogą zostać opublikowane i widoczne dla użytkowników.