Engage SDK Health and Fitness:第三方技术集成说明

随时随地触达用户,提升应用互动度。集成 Engage SDK,在合集、Entertainment Space 和 Play 商店等多个设备端展示途径中,直接向用户推送个性化推荐和接续内容。集成后,APK 平均大小增加不到 50 KB(压缩后),大多数应用需要大约一周的开发者时间。如需了解详情,请访问我们的业务网站。

本指南包含面向开发者合作伙伴的说明,介绍了如何将健康与健身内容传送到 Engage 内容途径。

类别支持和平台

Engage SDK 途径资格条件取决于应用的内容分类。请使用下表确定您是否有资格在特定平台上展示商品:

状态 内容分类或应用场景 支持的平台
支持
(可在所有平台上展示)
  • 健身课程
  • 健身习惯
  • 放松和冥想
  • 路线 / 小径探索
  • 膳食规划
  • 集合
  • Play 商店“应用”标签页
  • Play 商店中的“我”标签页
  • Play 商店商品详情页面
不受支持
  • BMI 计算器
  • 身体活动追踪器 / 计步器
  • 卡路里计数器
  • 睡眠监测器
  • 工具 / 遥控器
  • 医疗应用

集成详情

本部分详细介绍了与 Engage SDK 集成以提供健康与健身内容所需的步骤、数据模型和术语。

术语

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

  • 推荐集群用于显示来自单个开发者合作伙伴的个性化健康与健身建议。此类推荐既可以针对用户个性化定制,也可以一般化(例如,热门健身和健康)。使用这些标签来突出显示与健康和健身相关的文章或人物。

    • 推荐集群可以由 ArticleEntity、PersonEntity 或 EventEntity 组成,但不能由不同实体类型组合而成。

    您的推荐将采用如下结构:

    • 推荐集群:一个界面视图,其中包含来自同一开发者合作伙伴的一组推荐。

    • 实体:代表集群中单个内容的对象。此集成提供了一些会使用推荐集群显示的实体:

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

        图 1:界面,其中显示了推荐集群中的单个 ArticleEntity。
      • PersonEntity:PersonEntity 表示一个人。建议可以是突出显示教练或任何与健康和健身相关的人员等。

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

        图 3:界面,其中显示了推荐集群内的单个 EventEntity。
  • 接续集群用于在单个界面分组中显示来自多个开发者合作伙伴、最近与用户互动过的内容。每个开发者合作伙伴都可以在接续集群中广播最多 10 个实体。

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

    • ArticleEntity:ArticleEntity 表示与健康和健身相关的文本内容的推荐。此实体可用于表示未完成的新闻报道或用户希望从上次停下的地方继续消费的其他内容。例如:关于健康或健身相关主题的新闻摘要、博文摘要。

      图 6. 显示接续集群内的单个 ArticleEntity 的界面。
    • EventReservationEntity:EventReservationEntity 表示活动预订,可帮助用户跟踪即将开始或正在进行的健身和健康活动预订。例如:训练课程

      图 8. 显示接续集群内的单个 EventReservationEntity 的界面。
  • 精选集群用于在一个界面分组中展示来自多个开发者合作伙伴的精选实体。精选集群只有一个,并将显示在界面顶部附近,其展示位置的优先级高于所有推荐集群。每个开发者合作伙伴最多可以在精选集群中广播 10 个实体。

    • GenericFeaturedEntity:GenericFeaturedEntity 与推荐内容项的不同之处在于,精选内容项应代表开发者提供的单个热门内容,并且应代表用户会感兴趣且与用户相关的单个最重要内容。

      图 12:界面显示了“精选”集群中的单个主打 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.6.0'
}

摘要

设计的前提是已实现了绑定服务。

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

集群类型 集群限制 集群中的实体数下限 集群中的实体数上限
推荐集群 最多 7 个 至少 1 个 最多 50 个(ArticleEntity、PersonEntity 或 EventEntity)
接续集群 最多 1 个 至少 1 个 最多 20 个(ArticleEntity 或 EventReservationEntity)
精选集群 最多 1 个 至少 1 个 最多 20 个 (GenericFeaturedEntity)

第 1 步:提供实体数据

SDK 定义了不同的实体来代表每种内容类型。对于“Health & Fitness”类别,我们支持下列实体:

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

下表列出了每种类型的可用属性和相关要求。

GenericFeaturedEntity

属性 要求 说明 格式
操作 URI 必需

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

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

URI
海报图片 必需

如果提供了多张图片,我们只会显示 1 张图片。 建议的宽高比为 16:9

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

如需相关指导,请参阅图片规范。
标题 可选 实体的标题。

自由文本

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

说明 可选

用于描述实体的单段文字。

注意:系统会向用户显示说明或副标题列表,但不会同时显示两者。

自由文本

建议的文本大小:180 个字符

字幕列表 可选

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

注意:系统会向用户显示说明或副标题列表,但不会同时显示两者。

自由文本

每个字幕建议的文本大小:最多 50 个字符

徽章 可选

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

在图片/视频上进行特殊的用户体验处理,例如在图片上叠加徽章

  • “实时动态”
  • 文章阅读时长
徽章 - 文字 可选

徽章的标题

注意:徽章必须包含文字或图片

自由文本

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

徽章 - 图片 可选

小图片

特殊的用户体验处理,例如在图片/视频缩略图上叠加徽章。

注意:徽章必须包含文字或图片

如需相关指导,请参阅图片规范。
内容类别 可选 描述实体中内容的类别。

枚举列表

如需相关指导,请参阅“内容分类”部分。

ArticleEntity

属性 要求 说明 格式
操作 URI 必需

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

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

URI
标题 必需 实体的标题。

自由文本

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

海报图片 可选

如果提供了多张图片,我们只会显示 1 张图片。 建议的宽高比为 16:9

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

如需相关指导,请参阅图片规范。
来源 - 标题 可选 作者、组织或报告者的名称

自由文本

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

来源 - 图片 可选 来源(例如作者、组织、记者)的图片 如需相关指导,请参阅图片规范。
说明 可选

用于描述实体的单段文字。

注意:系统会向用户显示说明或副标题列表,但不会同时显示两者。

自由文本

建议的文本大小:180 个字符

字幕列表 可选

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

注意:系统会向用户显示说明或副标题列表,但不会同时显示两者。

自由文本

每个字幕建议的文本大小:最多 50 个字符

徽章 可选

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

在图片/视频上进行特殊的用户体验处理,例如在图片上叠加徽章

  • “实时动态”
  • 文章阅读时长
徽章 - 文字 可选

徽章的标题

注意:徽章必须包含文字或图片

自由文本

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

徽章 - 图片 可选

小图片

特殊的用户体验处理,例如在图片/视频缩略图上叠加徽章。

注意:徽章必须包含文字或图片

如需相关指导,请参阅图片规范。
内容发布时间 可选 这是内容在应用中发布 / 更新时的纪元时间戳(以毫秒为单位)。 纪元时间戳(以毫秒为单位)
上次互动时长 必需(有条件)

用户上次与此实体互动时的纪元时间戳(以毫秒为单位)。

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

纪元时间戳(以毫秒为单位)
进度百分比 必需(有条件)

用户迄今为止已使用的完整内容的百分比。

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

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

枚举列表

如需相关指导,请参阅“内容分类”部分。

PersonEntity

属性 要求 说明 格式
操作 URI 必需

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

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

URI
个人资料 - 姓名 必需 个人资料名称、ID 或标识名,例如“John Doe”“@TeamPixel”等。

字符串

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

个人资料 - 头像 必需

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

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

如需相关指导,请参阅图片规范。
个人资料 - 附加文字 可选 自由文本,例如个人资料标识名。

自由文本

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

个人资料 - 附加图片 可选 小图片,例如验证徽章。 如需相关指导,请参阅图片规范。
标题图片 可选

如果提供了多张图片,我们只会显示 1 张图片。 建议的宽高比为 16:9

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

如需相关指导,请参阅图片规范。
热门程度 - 计数 可选

表明关注者数量或人气值,例如“370 万”。

注意:如果同时提供了“计数”和“计数值”,系统将使用“计数”

字符串

建议的文本大小:计数 + 标签总计不超过 20 个字符

热门程度 - 计数 可选

关注者数量或人气值。

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

长边
热门程度 - 标签 可选 指明热门程度标签。例如“点赞”。

字符串

建议的文本大小:计数 + 标签总计不超过 20 个字符

热门程度 - 视觉 可选

表明互动的目的,例如,显示“赞”图标的图片、表情符号。

可以提供多张图片,但部分图片可能不会显示在所有外形规格的设备上。

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

如需相关指导,请参阅图片规范。
评分 - 最大值 必填

评分量表的最大值。

如果同时提供当前评分值,则必须提供。

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

评分量表的当前值。

如果同时提供最大评分值,则必须提供。

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

实体评分的计数。

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

字符串
评分 - 计数值 可选

实体评分的计数。

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

长边
位置 - 国家/地区 可选 此人所在或服务的国家/地区。

自由文本

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

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

自由文本

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

Location - Display Address 可选 系统会向用户显示此人所在或提供服务的地址。

自由文本

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

Location - Street Address 可选 此人所在或服务的街道地址(如果适用)。

自由文本

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

地理位置 - 州/省 可选 此人所在或服务的州/省级行政区(如适用)。

自由文本

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

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

自由文本

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

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

自由文本

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

徽章 可选

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

徽章 - 文字 可选

徽章的标题

注意:徽章必须包含文字或图片

自由文本

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

徽章 - 图片 可选

小图片

特殊的用户体验处理,例如在图片/视频缩略图上叠加徽章。

注意:徽章必须包含文字或图片

如需相关指导,请参阅图片规范。
说明 可选

用于描述实体的单段文字。

注意:系统会向用户显示说明或副标题列表,但不会同时显示两者。

自由文本

建议的文本大小: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 的安全空间

如需相关指导,请参阅图片规范。
位置 - 国家/地区 必需(有条件)

活动举办地所在的国家/地区。

注意:对于 IN_PERSON 或 HYBRID 活动,此字段为必填字段

自由文本

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

位置 - 城市 必需(有条件)

活动举办地所在的城市。

注意:对于 IN_PERSON 或 HYBRID 活动,此字段为必填字段

自由文本

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

Location - Display Address 必需(有条件)

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

注意:对于 IN_PERSON 或 HYBRID 活动,此字段为必填字段

自由文本

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

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

自由文本

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

地理位置 - 州/省 可选 活动举办地所在的州或省/直辖市/自治区(如适用)。

自由文本

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

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

自由文本

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

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

自由文本

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

结束时间 可选

事件预计结束时的纪元时间戳。

注意:此值以毫秒为单位。

纪元时间戳(以毫秒为单位)
说明 可选

用于描述实体的单段文字。

注意:系统会向用户显示说明或副标题列表,但不会同时显示两者。

自由文本

建议的文本大小:180 个字符

字幕列表 可选

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

注意:系统会向用户显示说明或副标题列表,但不会同时显示两者。

自由文本

每个字幕建议的文本大小:最多 50 个字符

徽章 可选

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

徽章 - 文字 可选

徽章的标题

注意:徽章必须包含文字或图片

自由文本

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

徽章 - 图片 可选

小图片

特殊的用户体验处理,例如在图片/视频缩略图上叠加徽章。

注意:徽章必须包含文字或图片

如需相关指导,请参阅图片规范。
价格 - 当前价格 在特定条件下必需

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

如果提供原价,则必须提供。

自由文本
Price - StrikethroughPrice 可选 活动门票/通行证的原始价格。 自由文本
价格标注 可选 用于展示促销、活动、会员折扣的价格宣传信息(如果有)。

自由文本

建议的文本大小:少于 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(示例 - meetup)

如需相关指导,请参阅“内容分类”部分。

EventReservationEntity

属性 要求 说明 格式
操作 URI 必需

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

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

URI
标题 必需 实体的标题。

字符串

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

开始时间 必需

事件预计开始的时间戳。

注意:此值以毫秒为单位。

纪元时间戳(以毫秒为单位)
事件模式 必需

用于指明活动是线上、线下还是线上线下相结合的字段。

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

活动举办地所在的国家/地区。

注意:对于 IN_PERSON 或 HYBRID 活动,此字段为必填字段

自由文本

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

位置 - 城市 必需(有条件)

活动举办地所在的城市。

注意:对于 IN_PERSON 或 HYBRID 活动,此字段为必填字段

自由文本

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

Location - Display Address 必需(有条件)

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

注意:对于 IN_PERSON 或 HYBRID 活动,此字段为必填字段

自由文本

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

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

自由文本

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

地理位置 - 州/省 可选 活动举办地所在的州或省/直辖市/自治区(如适用)。

自由文本

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

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

自由文本

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

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

自由文本

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

海报图片 可选

如果提供了多张图片,我们只会显示 1 张图片。 建议的宽高比为 16:9

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

如需相关指导,请参阅图片规范。
结束时间 可选

事件预计结束时的纪元时间戳。

注意:此值以毫秒为单位。

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

服务提供商的名称。

注意:服务提供商必须提供文字或图片。

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

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

注意:服务提供商必须提供文字或图片。

如需相关指导,请参阅图片规范。
说明 可选

用于描述实体的单段文字。

注意:系统会向用户显示说明或副标题列表,但不会同时显示两者。

自由文本

建议的文本大小:180 个字符

字幕列表 可选

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

注意:系统会向用户显示说明或副标题列表,但不会同时显示两者。

自由文本

每个字幕建议的文本大小:最多 50 个字符

徽章 可选

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

徽章 - 文字 可选

徽章的标题

注意:徽章必须包含文字或图片

自由文本

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

徽章 - 图片 可选

小图片

特殊的用户体验处理,例如在图片/视频缩略图上叠加徽章。

注意:徽章必须包含文字或图片

如需相关指导,请参阅图片规范。
预留 ID 可选 活动预留的预留 ID。 自由文本
价格 - 当前价格 在特定条件下必需

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

如果提供原价,则必须提供。

自由文本
Price - StrikethroughPrice 可选 活动门票/通行证的原始价格。 自由文本
价格标注 可选 用于展示促销、活动、会员折扣的价格宣传信息(如果有)。

自由文本

建议的文本大小:少于 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(示例 - meetup)

如需相关指导,请参阅“内容分类”部分。

图片规范

下表列出了图片素材资源必须遵循的规范:

宽高比 最小像素 建议的像素

方形 (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 - 在使用通用实体之前,请先查看观看集成指南中的实体。
    • TYPE_BOOKS - 在使用通用实体之前,请先查看 EbookEntity。
    • TYPE_AUDIOBOOKS - 在使用通用实体之前,请先查看 AudiobookEntity。
    • TYPE_SHOPPING - 在使用通用实体之前,请先查看 ShoppingEntity。
    • TYPE_FOOD_AND_DRINK - 在使用通用实体之前,请先查看餐饮集成指南中的实体。
  3. ContentCategory 字段是可选字段,如果内容不属于前面提到的任何类别,则应留空。

  4. 如果提供了多个内容分类,请按与内容的相关性顺序提供,将相关性最高的内容分类放在列表中的首位。

第 2 步:提供集群数据

建议在后台执行内容发布作业(例如,使用 WorkManager),并安排定期执行或按事件执行(例如,每当用户打开应用时,或当用户刚刚将商品添加到购物车时)。

AppEngagePublishClient 负责发布方集群。

以下 API 可用于在客户端中发布集群:

  • isServiceAvailable
  • publishRecommendationClusters
  • publishFeaturedCluster
  • publishContinuationCluster
  • publishUserAccountManagementRequest
  • updatePublishStatus
  • deleteRecommendationsClusters
  • deleteFeaturedCluster
  • deleteContinuationCluster
  • deleteUserManagementCluster
  • deleteClusters

isServiceAvailable

此 API 用于检查服务是否可供集成,以及内容是否可以呈现在设备上。

您可以检查要发布的每种集群类型的服务可用性。isServiceAvailable API 接受请求对象 ServiceAvailabilityRequest,其中包含需要检查服务可用性的集群类型。您可以从下表中找到 ServiceAvailabilityRequest 所需的 ClusterType 枚举值。

集群类型 集群类型常量 整数值
未知 TYPE_UNKNOWN 0
推荐集群 TYPE_RECOMMENDATION 1
精选集群 TYPE_FEATURED 2
接续集群 TYPE_CONTINUATION 3
用户管理集群 TYPE_ENGAGEMENT 8
订阅集群 TYPE_SUBSCRIPTION 12

Kotlin

val request = ServiceAvailabilityRequest.Builder()
    .addIntendedClusterType(ClusterType.TYPE_CONTINUATION)
    .addIntendedClusterType(ClusterType.TYPE_RECOMMENDATION)
    .build()

client.isServiceAvailable(request).addOnCompleteListener { task ->
    if (task.isSuccessful) {
        val availabilityMap = task.result
        if (availabilityMap[ClusterType.TYPE_CONTINUATION] == true) {
            // Proceed with publishing continuation content
        }
        if (availabilityMap[ClusterType.TYPE_RECOMMENDATION] == true) {
            // Proceed with publishing recommendation content
        }
    } else {
        // The IPC call itself fails, proceed with error handling logic here,
        // such as retry.
    }
}

Java

ServiceAvailabilityRequest request =
    new ServiceAvailabilityRequest.Builder()
        .addIntendedClusterType(ClusterType.TYPE_CONTINUATION)
        .addIntendedClusterType(ClusterType.TYPE_RECOMMENDATION)
        .build();

client.isServiceAvailable(request).addOnCompleteListener(task -> {
    if (task.isSuccessful()) {
        Map<Integer, Boolean> availabilityMap = task.getResult();
        if (Boolean.TRUE.equals(availabilityMap.get(ClusterType.TYPE_CONTINUATION))) {
            // Proceed with publishing continuation content
        }
        if (Boolean.TRUE.equals(availabilityMap.get(ClusterType.TYPE_RECOMMENDATION))) {
            // Proceed with publishing recommendation content
        }
    } else {
        // The IPC call itself fails, proceed with error handling logic here,
        // such as retry.
    }
});
有条件的服务可用性功能

某些集成应用会请求进行特殊配置,以便间歇性地启用和停用 Engage 服务,从而降低投放费用。不过,这种间歇性内容提取策略会对用户体验产生负面影响:系统不会呈现过时的内容,并且某些平台不会提供服务。

从 v1.6.0 开始,Engage SDK 允许检查特定集群类型的可用性。如果您的应用使用间歇性提取:

  • 延续性聚类(例如“继续阅读”和“活动预订”)在所有受支持的设备上仍默认处于启用状态。
  • 其他集群类型(例如建议)会间歇性地启用和停用。

如果此默认配置不符合您的需求,请与 engage-developers@google.com 联系。

对于 v1.6.0 之前的 SDK 版本(已弃用)

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 PublishFeaturedClusterRequest.Builder()
                .setFeaturedCluster(
                    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 建议发布登录卡片。如果提供商因任何原因无法发布登录卡片,建议调用 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());

deleteRecommendationsClusters

此 API 用于删除推荐集群的内容。

Kotlin

client.deleteRecommendationsClusters()

Java

client.deleteRecommendationsClusters();

当服务收到请求时,此 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_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 会从所有与指定集群类型匹配的集群中移除现有数据。客户端可以选择传递一个或多个集群类型。如果发生错误,系统将拒绝整个请求,并保留现有状态。

错误处理

强烈建议开发者监听来自发布 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 的形式返回错误,相应原因将作为错误代码包含在内。

错误代码 错误名称 注意
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 类的实例。这样一来,仍位于内存中的应用即可进行通信。

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),
                           com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                           /*scheduler=*/null)

// Register Featured Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_FEATURED),
                           com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                           /*scheduler=*/null)

// Register Continuation Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_CONTINUATION),
                           com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                           /*scheduler=*/null)
}

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),
                         com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                         /*scheduler=*/null);

// Register Featured Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
                         new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_FEATURED),
                         com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                         /*scheduler=*/null);

// Register Continuation Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
                         new IntentFilter(com.google.android.engage.service.Intents.ACTION_PUBLISH_CONTINUATION),
                         com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                         /*scheduler=*/null);

}
  • 在 AndroidManifest.xml 文件中使用 <receiver> 标记静态声明实现。这样一来,应用便可以在未运行时接收广播 intent,并且应用也可以发布内容。

<application>
   <receiver
      android:name=".AppEngageBroadcastReceiver"
      android:permission="com.google.android.engage.REQUEST_ENGAGE_DATA"
      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 商店后,您的推荐、精选和接续集群便可被发布并向用户显示。