Google 将打造一种设备端 surface,该 surface 可按行业整理用户的应用,并且支持全新的沉浸式体验,使用户能够以个性化的方式消费和发现应用内容。这种全屏体验可为开发者合作伙伴提供新的机会,使其能够通过自己的应用以外的专用渠道展示最优质的富媒体内容。
本指南包含面向开发者合作伙伴的说明,介绍了如何使用 Engage SDK 填充这个新的 surface 区域和现有的各种 Google surface,以便集成音频内容。
集成详情
术语
此集成包含以下三种集群类型:推荐、接续和精选。
推荐集群用于显示单个开发者合作伙伴按用户个性化需求推荐查看的内容。
您的推荐将采用如下结构:
推荐集群:一个界面视图,其中包含来自同一开发者合作伙伴的一组推荐。
实体:代表集群中的单个内容的对象。实体可以是播放列表、有声读物、播客等内容。如需查看受支持的实体类型的列表,请参阅提供实体数据部分。
接续集群用于在单个界面分组中显示来自多个开发者合作伙伴、最近与用户互动过的音频内容。每个开发者合作伙伴最多可以在接续集群中广播 10 个实体。
精选集群用于在单个界面分组中展示来自多个开发者合作伙伴的精选实体。精选集群只有一个,并将显示在界面顶部附近,其展示位置的优先级高于所有推荐集群。每个开发者合作伙伴最多可以在精选集群中广播 10 个实体。
准备工作
最低 API 级别:19
将 com.google.android.engage:engage-core
库添加到您的应用中:
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'
}
摘要
设计的前提是已实现了绑定服务。
对于不同的集群类型,客户端可以发布的数据受以下限制:
集群类型 | 集群限制 | 集群中的实体数上限 |
---|---|---|
推荐集群 | 最多 5 个 | 最多 50 个 |
接续集群 | 最多 1 个 | 最多 10 个 |
精选集群 | 最多 1 个 | 最多 10 个 |
第 1 步:提供实体数据
SDK 定义了不同的实体来代表每种内容类型。对于“Listen”类别,我们支持下列实体:
MusicAlbumEntity
MusicArtistEntity
MusicTrackEntity
MusicVideoEntity
PlaylistEntity
PodcastSeriesEntity
PodcastEpisodeEntity
LiveRadioStationEntity
AudiobookEntity
下面的表格列出了每种类型的可用属性和相关要求。
MusicAlbumEntity
MusicAlbumEntity
对象代表音乐专辑(例如,Taylor Swift 的《Midnights》)。
属性 | 要求 | 备注 |
---|---|---|
名称 | 必需 | 音乐专辑的标题。 |
海报图片 | 必需 | 必须至少提供一张图片。如需相关指导,请参阅图片规范。 |
信息页 URI | 必需 |
指向提供商应用中的音乐专辑详细信息的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
音乐人 | 必需 | 音乐专辑中的音乐人列表。 |
播放 URI | 可选 |
用于在提供商应用中开始播放专辑的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此常见问题解答 |
说明 | 可选 | 不得超过 200 个字符(如果提供)。 |
歌曲数 | 可选 | 音乐专辑中的歌曲数量。 |
流派 | 可选 | 音乐专辑中的流派列表。 |
专辑格式 | 可选 |
专辑(包括黑胶唱片和双黑胶唱片) 迷你专辑 单曲 自选辑 |
唱片公司 | 可选 | 与专辑相关联的唱片公司的列表。 |
已下载到设备上 | 可选 | 指示音乐专辑是否已下载到设备上的布尔值。 |
露骨内容 | 可选 |
指示内容是否为露骨内容的布尔值 包含露骨信息或收到家长指导警告的内容应设为 TRUE。露骨内容带有“E”标记。 |
发布日期 | 可选 | 专辑的发布日期(以从公元纪年开始计算的毫秒数表示)。 |
时长 | 可选 | 专辑的时长(以毫秒为单位)。 |
上次互动时长 | 可选 |
建议用于接续集群中的内容。可能会用于排名。 以从公元纪年开始计算的毫秒数表示 |
进度完成百分比 | 可选 |
建议用于接续集群中的内容。 介于 0 和 100 之间的整数。 |
MusicArtistEntity
MusicArtistEntity
对象代表音乐人(例如 Adele)。
属性 | 要求 | 备注 |
---|---|---|
名称 | 必需 | 音乐人的姓名。 |
海报图片 | 必需 | 必须至少提供一张图片。如需相关指导,请参阅图片规范。 |
信息页 URI | 必需 |
指向提供商应用中的音乐人详细信息的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
播放 URI | 可选 |
用于在提供商应用中开始播放音乐人歌曲的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
说明 | 可选 | 不得超过 200 个字符(如果提供)。 |
上次互动时长 | 可选 |
建议用于接续集群中的内容。可能会用于排名。 以从公元纪年开始计算的毫秒数表示 |
MusicTrackEntity
MusicTrackEntity
对象代表音乐曲目(例如 Coldplay 的《Yellow》)。
属性 | 要求 | 备注 |
---|---|---|
名称 | 必需 | 音乐曲目的标题。 |
海报图片 | 必需 | 必须至少提供一张图片。如需相关指导,请参阅图片规范。 |
播放 URI | 必需 |
用于在提供商应用中开始播放音乐曲目的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此常见问题解答 |
信息页 URI | 可选 |
指向提供商应用中的音乐曲目详细信息的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此常见问题解答 |
说明 | 可选 | 不得超过 200 个字符(如果提供)。 |
时长 | 可选 | 曲目的时长(以毫秒为单位)。 |
专辑 | 可选 | 歌曲所属专辑的名称。 |
音乐人 | 必需 | 音乐曲目的音乐人列表。 |
已下载到设备上 | 可选 | 指示音乐曲目是否已下载到设备上的布尔值。 |
露骨内容 | 可选 |
指示内容是否为露骨内容的布尔值 包含露骨信息或收到家长指导警告的内容应设为 TRUE。露骨内容带有“E”标记。 |
上次互动时长 | 可选 |
建议用于接续集群中的内容。可能会用于排名。 以从公元纪年开始计算的毫秒数表示 |
进度完成百分比 | 可选 |
建议用于接续集群中的内容。 介于 0 和 100 之间的整数。 |
MusicVideoEntity
MusicVideoEntity
对象代表音乐视频(例如,The Weeknd -《Take My Breath》[官方音乐视频])。
属性 | 要求 | 备注 |
---|---|---|
名称 | 必需 | 音乐视频的标题。 |
海报图片 | 必需 | 必须至少提供一张图片。如需相关指导,请参阅图片规范。 |
播放 URI | 必需 |
用于在提供商应用中开始播放音乐视频的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
信息页 URI | 可选 |
指向提供商应用中的音乐视频详细信息的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
时长 | 可选 | 视频的时长(以毫秒为单位)。 |
观看次数 | 可选 | 视频的观看次数(采用自由文本格式)。 |
音乐人 | 可选 | 音乐视频的音乐人列表。 |
内容分级 | 可选 | 曲目的内容分级列表。 |
说明 | 可选 | 不得超过 200 个字符(如果提供)。 |
已下载到设备上 | 可选 | 指示音乐视频是否已下载到设备上的布尔值。 |
露骨内容 | 可选 |
指示内容是否为露骨内容的布尔值 包含露骨信息或收到家长指导警告的内容应设为 TRUE。露骨内容带有“E”标记。 |
上次互动时长 | 可选 |
建议用于接续集群中的内容。可能会用于排名。 以从公元纪年开始计算的毫秒数表示 |
进度完成百分比 | 可选 |
建议用于接续集群中的内容。 介于 0 和 100 之间的整数。 |
PlaylistEntity
PlaylistEntity
对象代表音乐播放列表(例如,美国十大热门播放列表)。
属性 | 要求 | 备注 |
---|---|---|
名称 | 必需 | 播放列表的标题。 |
海报图片 | 必需 | 必须至少提供一张图片。如需相关指导,请参阅图片规范。 |
播放 URI | 必需 |
用于在提供商应用中开始播放音乐播放列表的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
信息页 URI | 可选 |
指向提供商应用中的音乐播放列表详细信息的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
时长 | 可选 | 播放列表的时长(以毫秒为单位)。 |
歌曲数 | 可选 | 音乐播放列表中的歌曲数量。 |
说明 | 可选 | 不得超过 200 个字符(如果提供)。 |
已下载到设备上 | 可选 | 指示播放列表是否已下载到设备上的布尔值。 |
露骨内容 | 可选 |
指示内容是否为露骨内容的布尔值 包含露骨信息或收到家长指导警告的内容应设为 TRUE。露骨内容带有“E”标记。 |
上次互动时长 | 可选 |
建议用于接续集群中的内容。可能会用于排名。 以从公元纪年开始计算的毫秒数表示 |
进度完成百分比 | 可选 |
建议用于接续集群中的内容。 介于 0 和 100 之间的整数。 |
PodcastSeriesEntity
PodcastSeriesEntity
对象代表播客系列(例如《This American Life》)。
属性 | 要求 | 备注 |
---|---|---|
名称 | 必需 | 播客系列的标题。 |
海报图片 | 必需 | 必须至少提供一张图片。如需相关指导,请参阅图片规范。 |
信息页 URI | 必需 |
指向提供商应用中的播客系列详细信息的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
播放 URI | 可选 |
用于在提供商应用中开始播放播客系列的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
剧集数 | 可选 | 播客系列中的分集数量。 |
作品名称 | 可选 | 播客系列的作品名称。 |
主持人 | 可选 | 播客系列的主持人列表。 |
类型 | 可选 | 播客系列的类型列表。 |
已下载到设备上 | 可选 | 指示播客是否已下载到设备上的布尔值。 |
说明 | 可选 | 不得超过 200 个字符(如果提供)。 |
露骨内容 | 可选 |
指示内容是否为露骨内容的布尔值 包含露骨信息或收到家长指导警告的内容应设为 TRUE。露骨内容带有“E”标记。 |
上次互动时长 | 可选 |
建议用于接续集群中的内容。可能会用于排名。 以从公元纪年开始计算的毫秒数表示 |
PodcastEpisodeEntity
PodcastEpisodeEntity
对象代表播客系列(例如,Spark Bird《This American Life》第 754 集)。
属性 | 要求 | 备注 |
---|---|---|
名称 | 必需 | 播客分集的标题。 |
海报图片 | 必需 | 必须至少提供一张图片。如需相关指导,请参阅图片规范。 |
播放 URI | 必需 |
用于在提供商应用中开始播放播客分集的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
作品系列标题 | 必需 | 分集所属的播客系列的名称。 |
时长 | 必需 | 播客分集的时长(以毫秒为单位)。 |
发布日期 | 必需 | 播客的发布日期(以从公元纪年开始计算的毫秒数表示) |
信息页 URI | 可选 |
指向提供商应用中的播客分集详细信息的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
作品名称 | 可选 | 播客系列的作品名称。 |
分集索引 | 可选 | 系列中分集的索引(第一个索引为 1)。 |
主持人 | 可选 | 播客分集的主持人列表。 |
类型 | 可选 | 播客分集的类型列表。 |
已下载到设备上 | 可选 | 指示播客分集是否已下载到设备上的布尔值。 |
说明 | 可选 | 不得超过 200 个字符(如果提供)。 |
视频播客 | 可选 | 指示播客分集是否包含视频内容的布尔值 |
露骨内容 | 可选 |
指示内容是否为露骨内容的布尔值 包含露骨信息或收到家长指导警告的内容应设为 TRUE。露骨内容带有“E”标记。 |
接下来收听内容的类型 | 可选 |
建议用于接续集群中的内容。 TYPE_CONTINUE - 继续收听未听完的音频内容。 TYPE_NEXT - 继续收听系列中的新音频内容。 TYPE_NEW - 收听新发布的音频内容。 |
上次互动时长 | 可选 |
建议用于接续集群中的内容。可能会用于排名。 以从公元纪年开始计算的毫秒数表示 |
进度完成百分比 | 可选 |
建议用于接续集群中的内容。 介于 0 和 100 之间的整数。 |
LiveRadioStationEntity
LiveRadioStationEntity
对象代表直播电台(例如,98.1《The Breeze》)。
属性 | 要求 | 备注 |
---|---|---|
名称 | 必需 | 直播电台的标题。 |
海报图片 | 必需 | 必须至少提供一张图片。如需相关指导,请参阅图片规范。 |
播放 URI | 必需 |
用于在提供商应用中开始播放电台的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
信息页 URI | 可选 |
指向提供商应用中的电台详细信息的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此处的常见问题解答 |
频率 | 可选 | 电台的广播频率(例如“FM 98.1”)。 |
节目名称 | 可选 | 当前在电台播放的节目。 |
主持人 | 可选 | 电台的主持人列表。 |
说明 | 可选 | 不得超过 200 个字符(如果提供)。 |
上次互动时长 | 可选 |
建议用于接续集群中的内容。可能会用于排名。 以从公元纪年开始计算的毫秒数表示 |
AudiobookEntity
AudiobookEntity
对象代表有声读物(例如,Michelle Obama 的《Becoming》的有声读物)。
属性 | 要求 | 备注 |
---|---|---|
名称 | 必需 | |
海报图片 | 必需 | 必须至少提供一张图片。如需相关指导,请参阅图片规范。 |
作者 | 必需 | 必须提供至少一位作者的姓名。 |
讲述者 | 必需 | 必须提供至少一位讲述者的姓名。 |
操作链接 URI | 必需 |
指向有声读物提供商应用的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此常见问题解答 |
发布日期 | 可选 | 以从公元纪年开始计算的毫秒数表示(如果提供)。 |
说明 | 可选 | 不得超过 200 个字符(如果提供)。 |
价格 | 可选 | 自由文本 |
时长 | 可选 | 必须为正值(如果提供)。 |
类型 | 可选 | 与图书相关联的类型的列表。 |
系列名称 | 可选 | 有声读物所属的系列的名称(例如《哈利·波特》)。 |
系列单元索引 | 可选 | 有声读物在系列中的索引,其中 1 代表系列中的第一本有声读物。例如,如果《哈利·波特与阿兹卡班的囚徒》是《哈利·波特》系列的第 3 本图书,则应将其设置为 3。 |
继续收听类型 | 可选 |
TYPE_CONTINUE - 继续收听未听完的图书。 TYPE_NEXT - 继续收听系列中的新音频内容。 TYPE_NEW - 收听新发布的音频内容。 |
上次互动时长 | 在特定条件下必需 | 当项位于接续集群中时,必须提供。 以从公元纪年开始计算的毫秒数表示。 |
进度完成百分比 | 在特定条件下必需 |
当项位于接续集群中时,必须提供。 *新* 购买的有声读物可加入“继续阅读”集群中。 值必须大于 0 且小于 100。 |
DisplayTimeWindow - 设置要在界面上显示内容的时间范围 | ||
开始时间戳 | 可选 |
纪元时间戳,在其之后相应内容应显示在 surface 上。 如果未设置,相应内容将有资格显示在 surface 上。 以从公元纪年开始计算的毫秒数表示。 |
结束时间戳 | 可选 |
纪元时间戳,在其之后相应内容不再显示在 surface 上。 如果未设置,相应内容将有资格显示在 surface 上。 以从公元纪年开始计算的毫秒数表示。 |
图片规范
下面列出了图片资源必须遵循的规范:
宽高比 | 要求 | 最小像素 | 建议的像素 |
---|---|---|---|
方形 (1x1) | 必需 | 300x300 | 1200x1200 |
横向 (1.91x1) | 可选 | 600x314 | 1200x628 |
纵向 (4x5) | 可选 | 480x600 | 960x1200 |
文件格式
PNG、JPG、静态 GIF、WebP
文件大小上限
5120 KB
其他建议
- 图片安全区域:将重要内容放在图片中间 80% 的区域内。
示例
MusicAlbumEntity musicAlbumEntity =
new MusicAlbumEntity.Builder()
.setName(NAME)
.addPosterImage(new Image.Builder()
.setImageUri(Uri.parse("http://www.x.com/image.png"))
.setImageHeightInPixel(960)
.setImageWidthInPixel(408)
.build())
.setPlayBackUri("https://play.google/album/play")
.setInfoPageUri("https://play.google/album/info")
.setDescription("A description of this album.")
.addArtist("Artist")
.addGenre("Genre")
.addMusicLabel("Label")
.addContentRating("Rating")
.setSongsCount(960)
.setReleaseDateEpochMillis(1633032895L)
.setDurationMillis(1633L)
.build();
AudiobookEntity audiobookEntity =
new AudiobookEntity.Builder()
.setName("Becoming")
.addPosterImage(new Image.Builder()
.setImageUri(Uri.parse("http://www.x.com/image.png"))
.setImageHeightInPixel(960)
.setImageWidthInPixel(408)
.build())
.addAuthor("Michelle Obama")
.addNarrator("Michelle Obama")
.setActionLinkUri(
Uri.parse("https://play.google/audiobooks/1"))
.setDurationMillis(16335L)
.setPublishDateEpochMillis(1633032895L)
.setDescription("An intimate, powerful, and inspiring memoir")
.setPrice("$16.95")
.addGenre("biography")
.build();
第 2 步:提供集群数据
建议在后台执行内容发布作业(例如,使用 WorkManager),并安排定期执行或按事件执行(例如,每当用户打开应用时,或当用户刚刚将商品添加到购物车时)。
AppEngagePublishClient
负责发布集群。以下 API 在该客户端中可用:
isServiceAvailable
publishRecommendationClusters
publishFeaturedCluster
publishContinuationCluster
publishUserAccountManagementRequest
updatePublishStatus
deleteRecommendationsClusters
deleteFeaturedCluster
deleteContinuationCluster
deleteUserManagementCluster
deleteClusters
isServiceAvailable
此 API 用于检查服务是否可供集成,以及内容是否可以呈现在设备上。
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
此 API 用于发布 RecommendationCluster
对象列表。
Kotlin
client.publishRecommendationClusters( PublishRecommendationClustersRequest.Builder() .addRecommendationCluster( RecommendationCluster.Builder() .addEntity(entity1) .addEntity(entity2) .setTitle("Trending music") .build()) .build())
Java
client.publishRecommendationClusters( new PublishRecommendationClustersRequest.Builder() .addRecommendationCluster( new RecommendationCluster.Builder() .addEntity(entity1) .addEntity(entity2) .setTitle("Trending music") .build()) .build());
当服务收到请求时,系统会在一项事务中执行以下操作:
- 系统会移除开发者合作伙伴的现有
RecommendationCluster
数据。 - 系统会解析请求中的数据,并将其存储在经过更新的推荐集群中。
如果发生错误,系统将拒绝整个请求,并保留现有状态。
publishFeaturedCluster
此 API 用于发布 FeaturedCluster
对象列表。
Kotlin
client.publishFeaturedCluster( PublishFeaturedClusterRequest.Builder() .setFeaturedCluster( FeaturedCluster.Builder() ... .build()) .build())
Java
client.publishFeaturedCluster( new PublishFeaturedClusterRequest.Builder() .setFeaturedCluster( new FeaturedCluster.Builder() ... .build()) .build());
当服务收到请求时,系统会在一项事务中执行以下操作:
- 系统会移除开发者合作伙伴的现有
FeaturedCluster
数据。 - 系统会解析请求中的数据,并将其存储在经过更新的精选集群中。
如果发生错误,系统将拒绝整个请求,并保留现有状态。
publishContinuationCluster
此 API 用于发布 ContinuationCluster
对象。
Kotlin
client.publishContinuationCluster( PublishContinuationClusterRequest.Builder() .setContinuationCluster( ContinuationCluster.Builder() .addEntity(entity1) .addEntity(entity2) .build()) .build())
Java
client.publishContinuationCluster( PublishContinuationClusterRequest.Builder() .setContinuationCluster( ContinuationCluster.Builder() .addEntity(entity1) .addEntity(entity2) .build()) .build())
当服务收到请求时,系统会在一项事务中执行以下操作:
- 系统会移除开发者合作伙伴的现有
ContinuationCluster
数据。 - 系统会解析请求中的数据,并将其存储在经过更新的接续集群中。
如果发生错误,系统将拒绝整个请求,并保留现有状态。
publishUserAccountManagementRequest
此 API 用于发布登录卡片。登录操作会将用户定向到应用的登录页面,以便应用能够发布内容(或提供更个性化的内容)。
以下元数据是登录卡片的一部分:
属性 | 要求 | 说明 |
---|---|---|
操作 URI | 必需 | 指向操作的深层链接(比如进入应用登录页面) |
图片 | 可选;如果不提供图片,则必须提供标题 |
卡片上显示的图片 宽高比为 16x9 且分辨率为 1264x712 的图片 |
标题 | 可选;如果不提供标题,则必须提供图片 | 卡片上的标题 |
操作文本 | 可选 | CTA 上显示的文字(比如“登录”) |
副标题 | 可选 | 卡片上的可选副标题 |
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());
当服务收到请求时,系统会在一项事务中执行以下操作:
- 系统会移除开发者合作伙伴的现有
UserAccountManagementCluster
数据。 - 系统会解析请求中的数据,并将其存储在经过更新的 UserAccountManagementCluster 集群中。
如果发生错误,系统将拒绝整个请求,并保留现有状态。
updatePublishStatus
如果由于任何内部业务原因,所有集群均未发布,我们强烈建议使用 updatePublishStatus API 更新发布状态。 这样做非常重要,因为:
- 在所有情况下都提供状态,即使内容已发布 (STATUS == PUBLISHED) 也不例外,这一点至关重要,因为只有这样才能填充信息中心,以便信息中心使用此明确状态传达集成的运行状况和其他指标。
- 如果未发布任何内容,但集成状态未被破坏 (STATUS == NOT_PUBLISHED),Google 可避免在应用运行状况信息中心内触发提醒。它会确认内容是因提供商意料之中的情况而未发布。
- 它可以帮助开发者深入了解数据发布/未发布的时间。
- Google 可能会借助状态代码促使用户在应用中执行某些操作,以便他们看到或处理应用内容。
下面列出了符合条件的发布状态代码:
// 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
如果内容因用户未登录而未发布,Google 建议发布登录卡片。 如果提供商因任何原因无法发布登录卡片,我们建议调用 updatePublishStatus API 并将状态代码设为 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
此 API 用于删除推荐集群的内容。
Kotlin
client.deleteRecommendationClusters()
Java
client.deleteRecommendationClusters();
当服务收到请求时,此 API 会从建议集群中移除现有数据。如果发生错误,系统将拒绝整个请求,并保留现有状态。
deleteFeaturedCluster
此 API 用于删除精选集群的内容。
Kotlin
client.deleteFeaturedCluster()
Java
client.deleteFeaturedCluster();
当服务收到请求时,此 API 会从精选集群中移除现有数据。如果发生错误,系统将拒绝整个请求,并保留现有状态。
deleteContinuationCluster
此 API 用于删除接续集群的内容。
Kotlin
client.deleteContinuationCluster()
Java
client.deleteContinuationCluster();
当服务收到请求时,此 API 会从接续集群中移除现有数据。如果发生错误,系统将拒绝整个请求,并保留现有状态。
deleteUserManagementCluster
此 API 用于删除 UserAccountManagement 集群的内容。
Kotlin
client.deleteUserManagementCluster()
Java
client.deleteUserManagementCluster();
当服务收到请求时,此 API 会从 UserAccountManagement 集群中移除现有数据。如果发生错误,系统将拒绝整个请求,并保留现有状态。
deleteClusters
此 API 用于删除给定集群类型的内容。
Kotlin
client.deleteClusters( DeleteClustersRequest.Builder() .addClusterType(ClusterType.TYPE_FEATURED) .addClusterType(ClusterType.TYPE_RECOMMENDATION) ... .build())
Java
client.deleteClusters( new DeleteClustersRequest.Builder() .addClusterType(ClusterType.TYPE_FEATURED) .addClusterType(ClusterType.TYPE_RECOMMENDATION) ... .build());
当服务收到请求时,此 API 会从所有与指定集群类型匹配的集群中移除现有数据。客户端可以选择传递一个或多个集群类型。如果发生错误,系统将拒绝整个请求,并保留现有状态。
错误处理
强烈建议开发者监听来自发布 API 的任务结果,以便执行后续操作,从而恢复并重新提交成功的任务。
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
}
}
}
});
系统将以 AppEngageException
的形式返回错误,相应原因将作为错误代码包含在内。
错误代码 | 错误名称 | 备注 |
---|---|---|
1 |
SERVICE_NOT_FOUND |
服务在给定设备上不可用。 |
2 |
SERVICE_NOT_AVAILABLE |
服务在给定设备上可用,但在调用时不可用(例如,服务已被明确停用)。 |
3 |
SERVICE_CALL_EXECUTION_FAILURE |
任务执行因线程问题而失败。在这种情况下,可以重试。 |
4 |
SERVICE_CALL_PERMISSION_DENIED |
不允许调用方进行服务调用。 |
5 |
SERVICE_CALL_INVALID_ARGUMENT |
请求包含无效数据(例如,集群数量超过允许的上限)。 |
6 |
SERVICE_CALL_INTERNAL |
服务端出现错误。 |
7 |
SERVICE_CALL_RESOURCE_EXHAUSTED |
服务调用过于频繁。 |
第 3 步:处理广播 intent
除了通过作业发出发布内容 API 调用外,还需要设置 BroadcastReceiver
来接收内容发布请求。
广播 intent 主要用于重新激活应用和强制同步数据。不应过于频繁地发送广播 intent。仅在 Engage Service 确定内容可能已过时(例如,内容是一周前的)的情况下,广播 intent 才会触发。这样一来,开发者将更加确信,即使应用长时间未执行,用户也能够获得新鲜的内容体验。
必须通过以下两种方式设置 BroadcastReceiver
:
- 使用
Context.registerReceiver()
动态注册BroadcastReceiver
类的实例。这样一来,仍位于内存中的应用即可进行通信。
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));
}
- 在
AndroidManifest.xml
文件中使用<receiver>
标记对实现进行静态声明。这样一来,应用便可以在未运行时接收广播 intent,并且应用也可以发布内容。
<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>
服务将发送以下 intent:
com.google.android.engage.action.PUBLISH_RECOMMENDATION
建议在收到此 intent 时启动publishRecommendationClusters
调用。com.google.android.engage.action.PUBLISH_FEATURED
建议在收到此 intent 时启动publishFeaturedCluster
调用。com.google.android.engage.action.PUBLISH_CONTINUATION
建议在收到此 intent 时启动publishContinuationCluster
调用。
集成工作流程
如需查看在集成完成后验证集成的分步指南,请参阅 Engage 开发者集成工作流程。
常见问题解答
如需查看常见问题解答,请参阅 Engage SDK 常见问题解答。
联系人
如果在集成过程中有任何疑问,请与 engage-developers@google.com 联系。我们的团队会尽快回复您。
后续步骤
完成此集成后,请执行下列后续步骤:
- 发送电子邮件至 engage-developers@google.com,并将可供 Google 测试的集成 APK 添加为附件。
- Google 将在内部执行验证和审核,以确保集成可按预期运行。如果需要进行更改,Google 将与您联系,告知您任何必要的详细信息。
- 测试完成,如果无需进行任何更改,Google 将与您联系,以向您说明您已可以开始将经过更新的集成 APK 发布到 Play 商店。
- 在 Google 确认经过更新的 APK 已发布到 Play 商店后,您的推荐、精选和接续集群便会发布并向用户显示。