Engage SDK 健康与健身:第三方技术集成说明

Google 正在构建一个设备上的界面,该界面按垂直行业组织用户的应用,并为个性化应用内容使用和发现提供新的沉浸式体验。此全屏体验为开发者合作伙伴提供了一个机会,让他们能够在应用之外的专用渠道中展示其最佳的丰富内容。本指南包含开发者合作伙伴集成其健康与健身内容的说明,使用 Engage SDK 来填充此新的界面区域。

集成详情

术语

此集成包括以下三种集群类型:**推荐**、**精选**和**续播**。

  • **推荐**集群显示来自单个开发者合作伙伴的个性化健康与健身建议。这些推荐可以针对用户个性化,也可以泛化(例如,热门健身和健康)。使用这些来显示与健康和健身相关的文章或人员。

    • 推荐集群可以由ArticleEntityPersonEntityEventEntity组成,但不能混合使用不同类型的实体。

    您的推荐采用以下结构

    • **推荐集群:**包含来自同一开发者合作伙伴的一组推荐的 UI 视图。

    • **实体:**表示集群中单个项目的对象。此集成提供了一些将使用推荐集群显示的实体

      • **ArticleEntity**:ArticleEntity 表示与健康和健身相关的基于文本内容的推荐。它可用于文章、博文、营销内容、新闻片段等。

        图 1:**显示推荐集群中单个 ArticleEntity 的 UI。
      • **PersonEntity**:PersonEntity 表示一个人。推荐可能是突出显示教练或任何与健康和健身相关的人员等。

        图 2:**显示推荐集群中单个 PersonEntity 的 UI。
      • **EventEntity**:EventEntity 表示未来发生的事件。事件开始时间是需要传达给用户的关键信息。此实体可用于显示与健康和健身相关的事件,例如献血活动、培训课程、健身房或瑜伽课程等。

        图 3:**显示推荐集群中单个 EventEntity 的 UI。
  • **续播**集群显示用户最近参与的来自多个开发者合作伙伴的内容,这些内容在一个 UI 分组中。每个开发者合作伙伴最多允许在续播集群中广播 10 个实体。

    您的续播内容可以采用以下结构

    • ArticleEntity:ArticleEntity 代表与健康和健身相关的文本内容的推荐。此实体可用于表示未完成的新闻文章或用户希望从上次阅读位置继续消费的其他内容。例如:有关健康或健身相关主题的新闻片段、博文片段。

      图 6. UI 显示 Continuation 集群中的单个 ArticleEntity。
    • EventReservationEntity:EventReservationEntity 代表活动的预订,并帮助用户跟踪即将举行的或正在进行的健身和健康活动预订。例如:训练课程

      图 8. UI 显示 Continuation 集群中的单个 EventReservationEntity。
  • Featured 集群是一个 UI 视图,它在一个 UI 分组中展示了来自众多开发者合作伙伴的选定英雄 GenericFeaturedEntity。只有一个 Featured 集群,它显示在 UI 顶部附近,优先级高于所有 Recommendation 集群。每个开发者合作伙伴都允许在 Featured 中广播一个支持类型的单个实体,Featured 集群中包含来自多个应用开发者的许多实体(可能属于不同类型)。

    • GenericFeaturedEntity:GenericFeaturedEntity 与 Recommendation 项目的不同之处在于,Featured 项目应用于开发者的单个顶级内容,并且应代表对用户来说最有趣和最相关 的单个最重要的内容。

      图 12:UI 显示 Featured 集群中的单个英雄 GenericFeaturedEntity 卡片

准备工作

最低 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'
}

摘要

此设计基于 绑定服务 的实现。

客户端可以发布的数据受以下不同集群类型的限制

集群类型 集群限制 集群中的最小实体限制 集群中的最大实体限制
Recommendation 集群 最多 5 个 至少 5 个 最多 25 个(ArticleEntityPersonEntityEventEntity
Continuation 集群 最多 1 个 至少 1 个 最多 10 个(ArticleEntityEventReservationEntity
Featured 集群 最多 1 个 至少 1 个 最多 10 个(GenericFeaturedEntity

步骤 1:提供实体数据

SDK 已定义不同的实体来表示每种项目类型。我们支持以下用于健康和健身类别的实体

  1. GenericFeaturedEntity
  2. ArticleEntity
  3. PersonEntity
  4. EventEntity
  5. EventReservationEntity

下表概述了每种类型的可用属性和要求。

GenericFeaturedEntity

属性 要求 描述 格式
操作 Uri 必填

指向提供商应用中实体的深度链接。

注意:您可以使用深度链接进行归因。 请参阅此常见问题解答

Uri
海报图片 必填

提供多个图片时,我们只会显示 1 张图片。建议的纵横比为 16:9

注意:如果提供了徽章,请确保图片顶部和底部的安全空间为 24 dp

请参阅 图片规格 以获取指导。
标题 可选 实体的标题。

自由文本

建议文本大小:50 个字符

描述 可选

一段描述实体的文本。

注意:将向用户显示描述或副标题列表,而不是两者都显示。

自由文本

建议文本大小:180 个字符

副标题列表 可选

最多 3 个副标题,每个副标题为一行文本。

注意:将向用户显示描述或副标题列表,而不是两者都显示。

自由文本

建议每个副标题的文本大小:最大 50 个字符

徽章 可选

每个徽章要么是自由文本(最多 15 个字符),要么是小图片。

图片/视频顶部的特殊 UX 处理,例如作为图片上的徽章叠加层

  • “实时更新”
  • 文章阅读时长
徽章 - 文本 可选

徽章的标题

注意:徽章需要文本或图片之一

自由文本

建议文本大小:最大 15 个字符

徽章 - 图片 可选

小图片

特殊的 UX 处理,例如作为图片/视频缩略图上的徽章叠加层。

注意:徽章需要文本或图片之一

请参阅 图片规格 以获取指导。
内容类别 可选 描述实体中内容的类别。

枚举列表

请参阅 内容类别部分 以获取指导。

ArticleEntity

属性 要求 描述 格式
操作 Uri 必填

指向提供商应用中实体的深度链接。

注意:您可以使用深度链接进行归因。 请参阅此常见问题解答

Uri
标题 必填 实体的标题。

自由文本

建议文本大小:最大 50 个字符

海报图片 可选

提供多个图片时,我们只会显示 1 张图片。建议的纵横比为 16:9

注意:强烈建议使用图片。如果提供了徽章,请确保图片顶部和底部的安全空间为 24 dp

请参阅 图片规格 以获取指导。
来源 - 标题 可选 作者、组织或记者的姓名

自由文本

建议文本大小:少于 25 个字符

来源 - 图片 可选 来源(如作者、组织、记者)的图片 请参阅 图片规格 以获取指导。
描述 可选

一段描述实体的文本。

注意:将向用户显示描述或副标题列表,而不是两者都显示。

自由文本

建议文本大小:180 个字符

副标题列表 可选

最多 3 个副标题,每个副标题为一行文本。

注意:将向用户显示描述或副标题列表,而不是两者都显示。

自由文本

建议每个副标题的文本大小:最大 50 个字符

徽章 可选

每个徽章要么是自由文本(最多 15 个字符),要么是小图片。

图片/视频顶部的特殊 UX 处理,例如作为图片上的徽章叠加层

  • “实时更新”
  • 文章阅读时长
徽章 - 文本 可选

徽章的标题

注意:徽章需要文本或图片之一

自由文本

建议文本大小:最大 15 个字符

徽章 - 图片 可选

小图片

特殊的 UX 处理,例如作为图片/视频缩略图上的徽章叠加层。

注意:徽章需要文本或图片之一

请参阅 图片规格 以获取指导。
内容发布时间 可选 这是内容在应用中发布/更新时的以毫秒为单位的纪元时间戳。 以毫秒为单位的纪元时间戳
上次参与时间 有条件地需要

用户上次与该实体交互时的以毫秒为单位的纪元时间戳。

注意:如果此实体是 Continuation 集群的一部分,则此字段是必填字段。

以毫秒为单位的纪元时间戳
进度百分比 有条件地需要

用户迄今为止消费的完整内容的百分比。

注意:如果此实体是 Continuation 集群的一部分,则此字段是必填字段。

介于 0~100(含)之间的整数值。
内容类别 可选 描述实体中内容的类别。

枚举列表

请参阅 内容类别部分 以获取指导。

PersonEntity

属性 要求 描述 格式
操作 Uri 必填

指向提供商应用中实体的深度链接。

注意:您可以使用深度链接进行归因。 请参阅此常见问题解答

Uri
个人资料 - 名称 必填 个人资料名称或 ID 或句柄,例如“John Doe”、“@TeamPixel”等。

字符串

建议文本大小:最大 50 个字符

个人资料 - 头像 必填

用户的个人资料图片或头像图片。

注意:必须是正方形 1:1 图片。

请参阅 图片规格 以获取指导。
个人资料 - 附加文本 可选 自由文本,如个人资料句柄。

自由文本

建议文本大小:最大 15 个字符

个人资料 - 附加图片 可选 小图片,如已验证徽章。 请参阅 图片规格 以获取指导。
标题图片 可选

提供多个图片时,我们只会显示 1 张图片。建议的纵横比为 16:9

注意:强烈建议使用图片。如果提供了徽章,请确保图片顶部和底部的安全空间为 24 dp

请参阅 图片规格 以获取指导。
受欢迎程度 - 计数 可选

表示标题图片。应与个人资料图片不同。如果还有其他图片可以帮助突出显示该人(例如他们的作品),则可以使用此图片。

注意:必须是 16:9 图片。如果提供了徽章,请确保图片顶部和底部的安全空间为 24 dp

字符串

建议文本大小:计数 + 标签组合的最大 20 个字符

受欢迎程度 - 计数值 可选

关注者数量或受欢迎程度值。

注意:如果您的应用不想处理如何针对不同显示尺寸优化大数字的逻辑,请提供计数值。如果同时提供计数和计数值,则使用计数。

长整型
受欢迎程度 - 标签 可选 指示受欢迎程度标签是什么。例如 -“点赞”。

字符串

建议文本大小:计数 + 标签组合的最大 20 个字符

受欢迎程度 - 视觉效果 可选

指示交互的用途。例如 - 显示点赞图标的图片、表情符号。

可以提供多个图片,但并非所有图片都可以在所有外形规格上显示。

注意:必须是正方形 1:1 图片

请参阅 图片规格 以获取指导。
评分 - 最大值 必填

评分量表的最大值。

如果还提供了评分的当前值,则必须提供。

数字 >= 0.0
评分 - 当前值 必填

评分量表的当前值。

如果还提供了评分的最大值,则必须提供。

数字 >= 0.0
评分 - 计数 可选

实体的评分计数。

注意:如果您的应用控制如何向用户显示计数,请提供此字段。使用简洁的字符串。例如,如果计数为 1,000,000,请考虑使用 1M 等缩写,以便计数不会在较小的显示尺寸上被截断。

字符串
评分 - 计数值 可选

实体的评分计数。

注意:如果您不想自己处理显示缩写逻辑,请提供此字段。如果同时存在计数和计数值,则将计数显示给用户。

长整型
位置 - 国家/地区 可选 该人所在或服务的国家/地区。

自由文本

建议文本大小:最大约 20 个字符

位置 - 城市 可选 该人所在或服务的城市。

自由文本

建议文本大小:最大约 20 个字符

位置 - 显示地址 可选 将向用户显示该人所在或服务的地址。

自由文本

建议文本大小:最大约 20 个字符

位置 - 街道地址 可选 该人所在或服务的街道地址(如果适用)。

自由文本

建议文本大小:最大约 20 个字符

位置 - 州/省 可选 该人所在或服务的州/省(如果适用)。

自由文本

建议文本大小:最大约 20 个字符

位置 - 邮政编码 可选 该人所在或服务的邮政编码(如果适用)。

自由文本

建议文本大小:最大约 20 个字符

位置 - 社区 可选 该人所在或服务的社区(如果适用)。

自由文本

建议文本大小:最大约 20 个字符

徽章 可选

每个徽章要么是自由文本(最多 15 个字符),要么是小图片。

徽章 - 文本 可选

徽章的标题

注意:徽章需要文本或图片之一

自由文本

建议文本大小:最大 15 个字符

徽章 - 图片 可选

小图片

特殊的 UX 处理,例如作为图片/视频缩略图上的徽章叠加层。

注意:徽章需要文本或图片之一

请参阅 图片规格 以获取指导。
描述 可选

一段描述实体的文本。

注意:将向用户显示描述或副标题列表,而不是两者都显示。

自由文本

建议文本大小:180 个字符

副标题列表 可选

最多 3 个副标题,每个副标题为一行文本。

注意:将向用户显示描述或副标题列表,而不是两者都显示。

自由文本

建议每个副标题的文本大小:最大 50 个字符

内容类别 可选 描述实体中内容的类别。

合格枚举列表

  • TYPE_HEALTH_AND_FITENESS(示例 - 瑜伽/健身教练)
  • TYPE_HOME_AND_AUTO(示例 - 水管工)
  • TYPE_SPORTS(示例 - 玩家)
  • TYPE_DATING

请参阅 内容类别部分 以获取指导。

EventEntity

属性 要求 描述 格式
操作 Uri 必填

指向提供商应用中实体的深度链接。

注意:您可以使用深度链接进行归因。 请参阅此常见问题解答

Uri
标题 必填 实体的标题。

字符串

建议文本大小:最大 50 个字符

开始时间 必填

活动预计开始时的纪元时间戳。

注意:这将以毫秒为单位表示。

以毫秒为单位的纪元时间戳
活动模式 必填

用于指示活动将是虚拟的、亲自的还是两者兼而有之的字段。

枚举:VIRTUAL、IN_PERSON 或 HYBRID
海报图片 必填

提供多个图片时,我们只会显示 1 张图片。建议的纵横比为 16:9

注意:强烈建议使用图片。如果提供了徽章,请确保图片顶部和底部的安全空间为 24 dp

请参阅 图片规格 以获取指导。
位置 - 国家/地区 有条件地需要

活动举办的国家/地区。

注意:对于亲自或混合活动,此字段是必填字段

自由文本

建议文本大小:最大约 20 个字符

位置 - 城市 有条件地需要

活动举办的城市。

注意:对于亲自或混合活动,此字段是必填字段

自由文本

建议文本大小:最大约 20 个字符

位置 - 显示地址 有条件地需要

活动举办地点的地址或场馆名称,应显示给用户。

注意:对于亲自或混合活动,此字段是必填字段

自由文本

建议文本大小:最大约 20 个字符

位置 - 街道地址 可选 活动举办地点的街道地址(如果适用)。

自由文本

建议文本大小:最大约 20 个字符

位置 - 州/省 可选 活动举办地点所在的州/省(如果适用)。

自由文本

建议文本大小:最大约 20 个字符

位置 - 邮政编码 可选 活动举办地点所在的邮政编码(如果适用)。

自由文本

建议文本大小:最大约 20 个字符

位置 - 社区 可选 活动举办地点所在的社区(如果适用)。

自由文本

建议文本大小:最大约 20 个字符

结束时间 可选

活动预计结束时的纪元时间戳。

注意:这将以毫秒为单位表示。

以毫秒为单位的纪元时间戳
描述 可选

一段描述实体的文本。

注意:将向用户显示描述或副标题列表,而不是两者都显示。

自由文本

建议文本大小:180 个字符

副标题列表 可选

最多 3 个副标题,每个副标题为一行文本。

注意:将向用户显示描述或副标题列表,而不是两者都显示。

自由文本

建议每个副标题的文本大小:最大 50 个字符

徽章 可选

每个徽章要么是自由文本(最多 15 个字符),要么是小图片。

徽章 - 文本 可选

徽章的标题

注意:徽章需要文本或图片之一

自由文本

建议文本大小:最大 15 个字符

徽章 - 图片 可选

小图片

特殊的 UX 处理,例如作为图片/视频缩略图上的徽章叠加层。

注意:徽章需要文本或图片之一

请参阅 图片规格 以获取指导。
价格 - 当前价格 有条件地需要

活动的票/通行证的当前价格。

如果提供了删除线价格,则必须提供。

自由文本
价格 - 删除线价格 可选 活动的票/通行证的原始价格。 自由文本
价格标注 可选 价格标注,用于在可用时突出显示促销、活动、会员折扣等。

自由文本

建议文本大小:少于 45 个字符(过长的文本可能会显示省略号)

内容类别 可选 描述实体中内容的类别。

合格枚举列表

  • TYPE_MOVIES_AND_TV_SHOWS(示例 - 电影院)
  • TYPE_DIGITAL_GAMES(示例 - 电子竞技)
  • TYPE_MUSIC(示例 - 音乐会)
  • TYPE_TRAVEL_AND_LOCAL(示例 - 旅游、节日)
  • TYPE_HEALTH_AND_FITENESS(示例 - 瑜伽课)
  • TYPE_EDUCATION(示例 - 课程)
  • TYPE_SPORTS(示例 - 足球比赛)
  • TYPE_DATING(示例 - 聚会)

请参阅 内容类别部分 以获取指导。

EventReservationEntity

属性 要求 描述 格式
操作 Uri 必填

指向提供商应用中实体的深度链接。

注意:您可以使用深度链接进行归因。 请参阅此常见问题解答

Uri
标题 必填 实体的标题。

字符串

建议文本大小:最大 50 个字符

开始时间 必填

活动预计开始时的纪元时间戳。

注意:这将以毫秒为单位表示。

以毫秒为单位的纪元时间戳
活动模式 必填

用于指示活动将是虚拟的、亲自的还是两者兼而有之的字段。

枚举:VIRTUAL、IN_PERSON 或 HYBRID
位置 - 国家/地区 有条件地需要

活动举办的国家/地区。

注意:对于亲自或混合活动,此字段是必填字段

自由文本

建议文本大小:最大约 20 个字符

位置 - 城市 有条件地需要

活动举办的城市。

注意:对于亲自或混合活动,此字段是必填字段

自由文本

建议文本大小:最大约 20 个字符

位置 - 显示地址 有条件地需要

活动举办地点的地址或场馆名称,应显示给用户。

注意:对于亲自或混合活动,此字段是必填字段

自由文本

建议文本大小:最大约 20 个字符

位置 - 街道地址 可选 活动举办地点的街道地址(如果适用)。

自由文本

建议文本大小:最大约 20 个字符

位置 - 州/省 可选 活动举办地点所在的州/省(如果适用)。

自由文本

建议文本大小:最大约 20 个字符

位置 - 邮政编码 可选 活动举办地点所在的邮政编码(如果适用)。

自由文本

建议文本大小:最大约 20 个字符

位置 - 社区 可选 活动举办地点所在的社区(如果适用)。

自由文本

建议文本大小:最大约 20 个字符

海报图片 可选

提供多个图片时,我们只会显示 1 张图片。建议的纵横比为 16:9

注意:强烈建议使用图片。如果提供了徽章,请确保图片顶部和底部的安全空间为 24 dp

请参阅 图片规格 以获取指导。
结束时间 可选

活动预计结束时的纪元时间戳。

注意:这将以毫秒为单位表示。

以毫秒为单位的纪元时间戳
服务提供商 - 名称 可选

服务提供商的名称。

注意:服务提供商需要文本或图片之一。

自由文本。例如,活动组织者/旅游的名称
服务提供商 - 图片 可选

服务提供商的徽标/图片。

注意:服务提供商需要文本或图片之一。

请参阅 图片规格 以获取指导。
描述 可选

一段描述实体的文本。

注意:将向用户显示描述或副标题列表,而不是两者都显示。

自由文本

建议文本大小:180 个字符

副标题列表 可选

最多 3 个副标题,每个副标题为一行文本。

注意:将向用户显示描述或副标题列表,而不是两者都显示。

自由文本

建议每个副标题的文本大小:最大 50 个字符

徽章 可选

每个徽章要么是自由文本(最多 15 个字符),要么是小图片。

徽章 - 文本 可选

徽章的标题

注意:徽章需要文本或图片之一

自由文本

建议文本大小:最大 15 个字符

徽章 - 图片 可选

小图片

特殊的 UX 处理,例如作为图片/视频缩略图上的徽章叠加层。

注意:徽章需要文本或图片之一

请参阅 图片规格 以获取指导。
预订 ID 可选 活动预订的预订 ID。 自由文本
价格 - 当前价格 有条件地需要

活动的票/通行证的当前价格。

如果提供了删除线价格,则必须提供。

自由文本
价格 - 删除线价格 可选 活动的票/通行证的原始价格。 自由文本
价格标注 可选 价格标注,用于在可用时突出显示促销、活动、会员折扣等。

自由文本

建议文本大小:少于 45 个字符(过长的文本可能会显示省略号)

评分 - 最大值 可选

评分量表的最大值。

如果还提供了评分的当前值,则必须提供。

数字 >= 0.0
评分 - 当前值 可选

评分量表的当前值。

如果还提供了评分的最大值,则必须提供。

数字 >= 0.0
评分 - 计数 可选

活动的评分计数。

注意:如果您的应用想要控制如何向用户显示此信息,请提供此字段。请提供可以显示给用户的简洁字符串。例如,如果计数为 1,000,000,请考虑使用 1M 等缩写,以便它不会在较小的显示尺寸上被截断。

字符串
评分 - 计数值 可选

活动的评分计数。

注意:如果您不想自己处理显示缩写逻辑,请提供此字段。如果同时存在计数和计数值,我们将使用计数显示给用户

长整型
内容类别 可选 描述实体中内容的类别。

合格枚举列表

  • TYPE_MOVIES_AND_TV_SHOWS(示例 - 电影院)
  • TYPE_DIGITAL_GAMES(示例 - 电子竞技)
  • TYPE_MUSIC(示例 - 音乐会)
  • TYPE_TRAVEL_AND_LOCAL(示例 - 旅游、节日)
  • TYPE_HEALTH_AND_FITENESS(示例 - 瑜伽课)
  • TYPE_EDUCATION(示例 - 课程)
  • TYPE_SPORTS(示例 - 足球比赛)
  • TYPE_DATING(示例 - 聚会)

请参阅 内容类别部分 以获取指导。

图片规格

此表中列出了图片资源的必填规格

纵横比 最小像素 推荐像素

正方形 (1x1)

首选

300x300 1200x1200
横向 (1.91x1) 600x314 1200x628

肖像方向 (4x5) 480x600 960x1200

图片需要托管在公共 CDN 上,以便 Google 能够访问它们。

文件格式

PNG、JPG、静态 GIF、WebP

最大文件大小

5120 KB

其他建议

  • **图片安全区域:** 将重要内容放置在图片中心 80% 的区域。
  • 使用透明背景,以便图片能够在深色和浅色主题设置中正确显示。

内容类别

内容类别允许应用发布属于多个类别的内容。这将内容与一些预定义的类别进行映射,例如:

  • TYPE_EDUCATION
  • TYPE_SPORTS
  • TYPE_MOVIES_AND_TV_SHOWS
  • TYPE_BOOKS
  • TYPE_AUDIOBOOKS
  • TYPE_MUSIC
  • TYPE_DIGITAL_GAMES
  • TYPE_TRAVEL_AND_LOCAL
  • TYPE_HOME_AND_AUTO
  • TYPE_BUSINESS
  • TYPE_NEWS
  • TYPE_FOOD_AND_DRINK
  • TYPE_SHOPPING
  • TYPE_HEALTH_AND_FITENESS
  • TYPE_MEDICAL
  • TYPE_PARENTING
  • TYPE_DATING

图片需要托管在公共 CDN 上,以便 Google 能够访问它们。

使用内容类别的指南

  1. 某些实体(如 **ArticleEntity** 和 **GenericFeaturedEntity**)可以使用任何内容类别。对于其他实体(如 **EventEntity**、**EventReservationEntity**、**PersonEntity**),则只能使用这些类别中的子集。在填充列表之前,请查看实体类型适用的类别列表。
  2. 对于某些内容类别,请使用特定的实体类型,而不是使用通用实体和 ContentCategory 的组合。

    • TYPE_MOVIES_AND_TV_SHOWS - 在使用通用实体之前,请查看 Watch 集成指南 中的实体。
    • TYPE_BOOKS - 在使用通用实体之前,请查看 EbookEntity
    • TYPE_AUDIOBOOKS - 在使用通用实体之前,请查看 AudiobookEntity
    • TYPE_SHOPPING - 在使用通用实体之前,请查看 ShoppingEntity
    • TYPE_FOOD_AND_DRINK - 在使用通用实体之前,请查看 Food 集成指南 中的实体。
  3. ContentCategory 字段是可选的,如果内容不属于前面提到的任何类别,则应将其留空。

  4. 如果提供了多个内容类别,请按与内容的相关性顺序提供,并将最相关的类别放在列表的第一位。

步骤 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("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());

当服务收到请求时,以下操作将在一个事务中进行:

  • 删除开发合作伙伴的现有 RecommendationCluster 数据。
  • 解析请求中的数据并将其存储在更新的推荐集群中。

如果发生错误,则整个请求将被拒绝,并保持现有状态。

publishFeaturedCluster

此 API 用于发布 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());

当服务收到请求时,以下操作将在一个事务中进行:

  • 删除开发合作伙伴的现有 FeaturedCluster 数据。
  • 解析请求中的数据并将其存储在更新的特色集群中。

如果发生错误,则整个请求将被拒绝,并保持现有状态。

publishContinuationCluster

此 API 用于发布 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());

当服务收到请求时,以下操作将在一个事务中进行:

  • 删除开发合作伙伴的现有 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 会建议发布登录卡片。如果出于任何原因提供商无法发布登录卡片,则建议使用状态代码 **NOT_PUBLISHED_REQUIRES_SIGN_IN** 调用 **updatePublishStatus** API。

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();

当服务收到请求时,它会从推荐集群中删除现有数据。如果发生错误,则整个请求将被拒绝,并保持现有状态。

deleteFeaturedCluster

此 API 用于删除特色集群的内容。

Kotlin

client.deleteFeaturedCluster()

Java

client.deleteFeaturedCluster();

当服务收到请求时,它会从特色集群中删除现有数据。如果发生错误,则整个请求将被拒绝,并保持现有状态。

deleteContinuationCluster

此 API 用于删除延续集群的内容。

Kotlin

client.deleteContinuationCluster()

Java

client.deleteContinuationCluster();

当服务收到请求时,它会从延续集群中删除现有数据。如果发生错误,则整个请求将被拒绝,并保持现有状态。

deleteUserManagementCluster

此 API 用于删除用户帐户管理集群的内容。

Kotlin

client.deleteUserManagementCluster()

Java

client.deleteUserManagementCluster();

当服务收到请求时,它会从用户帐户管理集群中删除现有数据。如果发生错误,则整个请求将被拒绝,并保持现有状态。

deleteClusters

此 API 用于删除给定集群类型的内容。

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());

当服务收到请求时,它会从与指定集群类型匹配的所有集群中删除现有数据。客户端可以选择传递一个或多个集群类型。如果发生错误,则整个请求将被拒绝,并保持现有状态。

错误处理

强烈建议侦听发布 API 的任务结果,以便可以采取后续操作来恢复并重新提交成功的任务。

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
                    }
                  }
                }
              });

错误将作为 AppEngageException 返回,其中包含错误代码作为原因。

错误代码 注意
SERVICE_NOT_FOUND 给定设备上没有此服务。
SERVICE_NOT_AVAILABLE 给定设备上有此服务,但在调用时不可用(例如,已明确禁用)。
SERVICE_CALL_EXECUTION_FAILURE 由于线程问题导致任务执行失败。在这种情况下,可以重试。
SERVICE_CALL_PERMISSION_DENIED 调用方无权进行服务调用。
SERVICE_CALL_INVALID_ARGUMENT 请求包含无效数据(例如,集群数量超过允许数量)。
SERVICE_CALL_INTERNAL 服务端出现错误。
SERVICE_CALL_RESOURCE_EXHAUSTED 服务调用过于频繁。

步骤 3:处理广播意图

除了通过作业进行内容发布 API 调用之外,还需要设置 BroadcastReceiver 以接收内容发布请求。

广播意图的主要目的是应用重新激活和强制数据同步。广播意图并非设计为频繁发送。仅当 Engage 服务确定内容可能已过时(例如,一周前)时才会触发它。这样,即使应用程序长时间未执行,用户也可以更有信心获得全新的内容体验。

BroadcastReceiver 必须通过以下两种方式进行设置:

  • 使用 Context.registerReceiver() 动态注册 BroadcastReceiver 类的实例。这使得仍然驻留在内存中的应用程序能够进行通信。

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));

}
  • AndroidManifest.xml 文件中使用 <receiver> 标记静态声明实现。这允许应用程序在未运行时接收广播意图,并允许应用程序发布内容。
<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>

服务发送以下 意图

  • com.google.android.engage.action.PUBLISH_RECOMMENDATION 建议在收到此意图时启动 publishRecommendationClusters 调用。

  • com.google.android.engage.action.PUBLISH_FEATURED 建议在收到此 Intent 时启动 publishFeaturedCluster 调用。
  • com.google.android.engage.action.PUBLISH_CONTINUATION 建议在收到此 Intent 时启动 publishContinuationCluster 调用。

集成工作流程

有关完成集成后验证集成步骤的逐步指南,请参阅 Engage 开发人员集成工作流程

常见问题

有关常见问题,请参阅 Engage SDK 常见问题解答

联系方式

如果您在集成过程中有任何疑问,请联系 [email protected]

后续步骤

完成此集成后,您的后续步骤如下:

  • 发送电子邮件至 [email protected],并附上您已集成的 APK,以便 Google 进行测试。
  • Google 会进行验证和内部审查,以确保集成按预期工作。如果需要更改,Google 会与您联系并提供必要的详细信息。
  • 测试完成后且不需要任何更改时,Google 会与您联系,通知您可以开始将更新的集成 APK 发布到 Play 商店。
  • 在 Google 确认您已更新的 APK 已发布到 Play 商店后,您的推荐精选续播集群可能会发布并对用户可见。