本指南包含面向开发者的说明,介绍了如何使用 Engage SDK 集成推荐视频内容,以便在各种 Google 途径(例如电视、移动设备和平板电脑)中填充推荐内容体验。
推荐功能利用推荐集群,在一个界面分组中显示来自多个应用的电影和电视节目。每个开发者合作伙伴最多可以在每个推荐集群中广播 25 个实体,并且每个请求最多可以包含 7 个推荐集群。
准备工作
在开始之前,请完成以下步骤。 1. 请验证您的应用是否以 API 级别 19 或更高级别为目标平台,以便进行此集成。
将
com.google.android.engage
库添加到您的应用中。集成时需要使用单独的 SDK:一个用于移动应用,另一个用于 TV 应用。
适用于移动设备
dependencies { implementation 'com.google.android.engage:engage-core:1.5.5 }
适用于电视
dependencies { implementation 'com.google.android.engage:engage-tv:1.0.2 }
在
AndroidManifest.xml
文件中将 Engage 服务环境设为生产环境。对于移动 APK
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
For tv apk
<meta-data android:name="com.google.android.engage.service.ENV" android:value="PRODUCTION"> </meta-data>
对前台服务执行发布操作。
最多每天发布一次推荐数据,由以下任一事件触发
- 用户当天的首次登录时间。(或)
- 当用户开始与应用互动时。
集成
AppEngagePublishClient
会发布推荐集群。使用 publishRecommendationClusters
方法发布 recommendations 对象。
使用 isServiceAvailable()
2 检查服务是否可供集成。
val client = AppEngagePublishClient(context)
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.
client.publishRecommendationClusters(recommendationRequest)
} else {
// Service is not available
}
} else {
// The IPC call itself fails, proceed with error handling logic here,
// such as retry.
}
}
推荐集群和发布请求
集群是实体的逻辑分组。以下代码示例介绍了如何根据您的偏好设置构建集群,以及如何为所有集群创建发布请求。
// cluster for popular movies
val recommendationCluster1 = RecommendationCluster
.Builder()
.addEntity(movie)
.addEntity(tvShow)
.setTitle("Popular Movies")
.build()
// cluster for top searches
val recommendationCluster2 = RecommendationCluster
.Builder()
.addEntity(movie)
.addEntity(tvShow)
.setTitle("Top Searches")
.build()
// creating a publishing request
val recommendationRequest = PublishRecommendationClustersRequest
.Builder()
.setSyncAcrossDevices(true)
.setAccountProfile(accountProfile)
.addRecommendationCluster(recommendationCluster1)
.addRecommendationCluster(recommendationCluster2)
.build()
创建账号个人资料
如需在 Google TV 上获得个性化体验,请提供账号和个人资料信息。使用 AccountProfile
提供:
- 账号 ID:表示用户在应用中的账号的唯一标识符。这可以是实际的账号 ID,也可以是经过适当混淆处理的版本。
- 个人资料 ID(可选):如果您的应用支持单个账号中的多个个人资料,请为特定用户个人资料提供唯一标识符。
- 语言区域(可选):您可以选择提供用户的首选语言。
如果您在
RecommendationRequest
中发送MediaActionFeedEntity
,此字段会很有用。
// If app only supports account
val accountProfile = AccountProfile.Builder()
.setAccountId("account_id")
.build();
// If app supports both account and profile
val accountProfile = AccountProfile.Builder()
.setAccountId("account_id")
.setProfileId("profile_id")
.build();
// set Locale
val accountProfile = AccountProfile.Builder()
.setAccountId("account_id")
.setProfileId("profile_id")
.setLocale("en-US")
.build();
当服务收到请求时,系统会在一项事务中执行以下操作:
- 系统会移除开发者合作伙伴的现有
RecommendationsCluster
数据。 - 系统会解析请求中的数据,并将其存储在经过更新的
RecommendationsCluster
中。如果发生错误,系统将拒绝整个请求,并保留现有状态。
跨设备同步
SyncAcrossDevices
标志用于控制是否与 Google TV 共享用户的推荐集群数据,以及是否在用户的设备(例如电视、手机、平板电脑)上提供这些数据。为了让建议生效,必须将其设置为 true。
征求用户意见
媒体应用必须提供明确的设置,以启用或停用跨设备同步。向用户说明好处,并存储用户的偏好设置一次,然后相应地在 publishRecommendations
请求中应用该偏好设置。如需充分利用跨设备功能,请验证应用是否已征得用户同意,并将 SyncAcrossDevices
设为 true
。
删除视频发现数据
如需在标准 60 天保留期限之前从 Google TV 服务器手动删除用户的数据,请使用 client.deleteClusters()
方法。收到请求后,该服务会删除账号个人资料或整个账号的所有现有视频发现数据。
DeleteReason
枚举定义了数据删除原因。以下代码会在用户退出账号时移除推荐内容。
// If the user logs out from your media app, you must make the following call
// to remove recommendations data from the current google TV device,
// otherwise, the recommendations data persists on the current
// google TV device until 60 days later.
client.deleteClusters(
new DeleteClustersRequest.Builder()
.setAccountProfile(AccountProfile())
.setReason(DeleteReason.DELETE_REASON_USER_LOG_OUT)
.build()
)
// If the user revokes the consent to share data with Google TV,
// you must make the following call to remove recommendations data from
// all current google TV devices. Otherwise, the recommendations data persists
// until 60 days later.
client.deleteClusters(
new DeleteClustersRequest.Builder()
.setAccountProfile(AccountProfile())
.setReason(DeleteReason.DELETE_REASON_LOSS_OF_CONSENT)
.build()
)
创建实体
SDK 定义了不同的实体来代表每种内容类型。推荐集群支持以下实体:
MediaActionFeedEntity
MovieEntity
TvShowEntity
说明
为每个实体提供简短说明;当用户将鼠标悬停在实体上时,系统会显示此说明,为用户提供更多详细信息。
平台专用播放 URI
为每个受支持的平台(Android TV、Android 或 iOS)创建播放 URI。 这样,系统就可以选择适当的 URI 在相应平台上播放视频。
在极少数情况下,如果所有平台的播放 URI 都相同,请为每个平台重复使用该 URI。
// Required. Set this when you want recommended entities to show up on
// Google TV
val playbackUriTv = PlatformSpecificUri
.Builder()
.setPlatformType(PlatformType.TYPE_ANDROID_TV)
.setActionUri(Uri.parse("https://www.example.com/entity_uri_for_tv"))
.build()
// Optional. Set this when you want recommended entities to show up on
// Google TV Android app
val playbackUriAndroid = PlatformSpecificUri
.Builder()
.setPlatformType(PlatformType.TYPE_ANDROID_MOBILE)
.setActionUri(Uri.parse("https://www.example.com/entity_uri_for_android"))
.build()
// Optional. Set this when you want recommended entities to show up on
// Google TV iOS app
val playbackUriIos = PlatformSpecificUri
.Builder()
.setPlatformType(PlatformType.TYPE_IOS)
.setActionUri(Uri.parse("https://www.example.com/entity_uri_for_ios"))
.build()
val platformSpecificPlaybackUris =
Arrays.asList(playbackUriTv, playbackUriAndroid, playbackUriIos)
// Provide appropriate rating for the system.
val contentRating = new RatingSystem
.Builder()
.setAgencyName("MPAA")
.setRating("PG-13")
.build()
海报图片
海报图片需要提供 URI 和像素尺寸(高度和宽度)。通过提供多张海报图片来定位不同的外形规格,但请确保所有图片的宽高比均为 16:9,且高度至少为 200 像素,以便正确显示“推荐”实体,尤其是在 Google 的 Entertainment Space 中。高度小于 200 像素的图片可能无法显示。
Image image1 = new Image.Builder()
.setImageUri(Uri.parse("http://www.example.com/entity_image1.png");)
.setImageHeightInPixel(300)
.setImageWidthInPixel(169)
.build()
Image image2 = new Image.Builder()
.setImageUri(Uri.parse("http://www.example.com/entity_image2.png");)
.setImageHeightInPixel(640)
.setImageWidthInPixel(360)
.build()
// And other images for different form factors.
val images = Arrays.asList(image1, image2)
建议原因
(可选)提供推荐原因,Google TV 可以使用该原因来构建向用户推荐特定电影或电视节目的原因。
//Allows us to construct reason: "Because it is top 10 on your Channel"
val topOnPartner = RecommendationReasonTopOnPartner
.Builder()
.setNum(10) //any valid integer value
.build()
//Allows us to construct reason: "Because it is popular on your Channel"
val popularOnPartner = RecommendationReasonPopularOnPartner
.Builder()
.build()
//Allows us to construct reason: "New to your channel, or Just added"
val newOnPartner = RecommendationReasonNewOnPartner
.Builder()
.build()
//Allows us to construct reason: "Because you watched Star Wars"
val watchedSimilarTitles = RecommendationReasonWatchedSimilarTitles
.addSimilarWatchedTitleName("Movie or TV Show Title")
.addSimilarWatchedTitleName("Movie or TV Show Title")
.Builder()
.build()
//Allows us to construct reason: "Recommended for you by ChannelName"
val recommendedForUser = RecommendationReasonRecommendedForUser
.Builder()
.build()
val watchAgain = RecommendationReasonWatchAgain
.Builder()
.build()
val fromUserWatchList = RecommendationReasonFromUserWatchlist
.Builder()
.build()
val userLikedOnPartner = RecommendationReasonUserLikedOnPartner
.Builder()
.setTitleName("Movie or TV Show Title")
.build()
val generic = RecommendationReasonGeneric.Builder().build()
显示时间窗口
如果实体应仅在有限的时间内提供,请设置自定义到期时间。如果未明确设置到期时间,实体将在 60 天后自动过期并被清除。因此,请仅在实体需要更快过期时设置到期时间。您可以指定多个此类播出信息时间范围。
val window1 = DisplayTimeWindow
.Builder()
.setStartTimeStampMillis(now()+ 1.days.toMillis())
.setEndTimeStampMillis(now()+ 30.days.toMillis())
val window2 = DisplayTimeWindow
.Builder()
.setEndTimeStampMillis(now()+ 30.days.toMillis())
val availabilityTimeWindows: List<DisplayTimeWindow> = listof(window1,window2)
DataFeedElementId
如果您已将媒体目录或媒体 Action Feed 与 Google TV 集成,则无需为电影或电视节目分别创建实体,而是可以创建包含必需字段 DataFeedElementId 的 MediaActionFeed 实体。此 ID 必须是唯一的,并且必须与 Media Actions Feed 中的 ID 一致,因为它有助于识别提取的 Feed 内容并执行媒体内容查询。
val id = "dataFeedEleemntId"
MovieEntity
以下示例展示了如何创建包含所有必填字段的 MovieEntity
:
val movieEntity = MovieEntity.Builder()
.setName("Movie name")
.setDescription("A sentence describing movie.")
.addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
.addPosterImages(images)
// Suppose the duration is 2 hours, it is 72000000 in milliseconds
.setDurationMills(72000000)
.build()
您可以提供其他数据,例如类型、内容分级、发布日期、推荐原因和播出时间范围,Google TV 可能会将这些数据用于增强显示或过滤目的。
val genres = Arrays.asList("Action", "Science fiction");
val rating1 = RatingSystem.Builder().setAgencyName("MPAA").setRating("pg-13").build();
val contentRatings = Arrays.asList(rating1);
//Suppose release date is 11-02-2025
val releaseDate = 1739233800000L
val movieEntity = MovieEntity.Builder()
...
.addGenres(genres)
.setReleaseDateEpochMillis(releaseDate)
.addContentRatings(contentRatings)
.setRecommendationReason(topOnPartner or watchedSimilarTitles)
.addAllAvailabilityTimeWindows(availabilityTimeWindows)
.build()
TvShowEntity
以下示例展示了如何创建包含所有必填字段的 TvShowEntity
:
val tvShowEntity = TvShowEntity.Builder()
.setName("Show title")
.setDescription("A sentence describing TV Show.")
.addPlatformSpecificPlaybackUri(platformSpecificPlaybackUris)
.addPosterImages(images)
.build();
(可选)提供其他数据,例如类型、内容分级、推荐原因、优惠价格、剧季数或播出时间范围,Google TV 可能会使用这些数据来增强显示效果或进行过滤。
val genres = Arrays.asList("Action", "Science fiction");
val rating1 = RatingSystem.Builder()
.setAgencyName("MPAA")
.setRating("pg-13")
.build();
val price = Price.Builder()
.setCurrentPrice("$14.99")
.setStrikethroughPrice("$16.99")
.build();
val contentRatings = Arrays.asList(rating1);
val seasonCount = 5;
val tvShowEntity = TvShowEntity.Builder()
...
.addGenres(genres)
.addContentRatings(contentRatings)
.setRecommendationReason(topOnPartner or watchedSimilarTitles)
.addAllAvailabilityTimeWindows(availabilityTimeWindows)
.setSeasonCount(seasonCount)
.setPrice(price)
.build()
MediaActionFeedEntity
以下示例展示了如何创建包含所有必填字段的 MediaActionFeedEntity
:
val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
.setDataFeedElementId(id)
.build()
您可以选择提供其他数据,例如说明、推荐原因和展示时间范围,Google TV 可能会将这些数据用于增强展示效果或过滤目的。
val mediaActionFeedEntity = MediaActionFeedEntity.Builder()
.setName("Movie name or TV Show name")
.setDescription("A sentence describing an entity")
.setRecommendationReason(topOnPartner or watchedSimilarTitles)
.addPosterImages(images)
.build()
通过实现这些步骤,开发者可以成功将视频内容推荐功能集成到 Google TV 中,从而提高用户发现内容和互动度,并为用户提供一致且个性化的观看体验,无论用户使用的是哪种设备。