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. 显示续播集群中单个 ArticleEntity 的 UI。
    • **EventReservationEntity:**EventReservationEntity 代表事件的预订,并帮助用户跟踪即将发生或正在进行的健身和健康事件预订。例如:培训课程

      图 8. 显示续播集群中单个 EventReservationEntity 的 UI。
  • **特色**集群在一个 UI 分组中展示来自多个开发者合作伙伴的实体选择。将有一个单独的特色集群,它出现在 UI 的顶部附近,优先于所有推荐集群。每个开发者合作伙伴最多允许在特色集群中广播 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.5.2'
}

总结

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

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

集群类型 集群限制 集群中实体的最小数量限制 集群中实体的最大数量限制
推荐集群 最多5个 至少5个 最多25个(ArticleEntityPersonEntityEventEntity
延续集群 最多1个 至少1个 最多10个(ArticleEntityEventReservationEntity
特色集群 最多1个 至少1个 最多10个(GenericFeaturedEntity

步骤1:提供实体数据

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

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

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

GenericFeaturedEntity

属性 要求 描述 格式
Action Uri 必填

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

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

Uri
海报图片 必填

提供多张图片时,我们只会显示一张图片。推荐宽高比为16:9。

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

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

自由文本

推荐文本大小:50个字符

描述 可选

一段描述实体的文本。

注意:只会向用户显示描述或副标题列表,不会同时显示两者。

自由文本

推荐文本大小:180个字符

副标题列表 可选

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

注意:只会向用户显示描述或副标题列表,不会同时显示两者。

自由文本

每个副标题的推荐文本大小:最多50个字符

徽章 可选

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

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

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

徽章的标题

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

自由文本

推荐文本大小:最多15个字符

徽章 - 图片 可选

小图片

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

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

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

枚举列表

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

ArticleEntity

属性 要求 描述 格式
Action Uri 必填

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

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

Uri
标题 必填 实体的标题。

自由文本

推荐文本大小:最多50个字符

海报图片 可选

提供多张图片时,我们只会显示一张图片。推荐宽高比为16:9。

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

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

自由文本

推荐文本大小:少于25个字符

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

一段描述实体的文本。

注意:只会向用户显示描述或副标题列表,不会同时显示两者。

自由文本

推荐文本大小:180个字符

副标题列表 可选

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

注意:只会向用户显示描述或副标题列表,不会同时显示两者。

自由文本

每个副标题的推荐文本大小:最多50个字符

徽章 可选

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

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

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

徽章的标题

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

自由文本

推荐文本大小:最多15个字符

徽章 - 图片 可选

小图片

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

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

请参阅图片规格以获得指导。
内容发布时间 可选 内容在应用中发布/更新时的纪元时间戳(毫秒)。 以毫秒为单位的纪元时间戳
上次参与时间 条件必填

用户上次与该实体交互时的纪元时间戳(毫秒)。

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

以毫秒为单位的纪元时间戳
进度百分比 条件必填

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

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

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

枚举列表

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

PersonEntity

属性 要求 描述 格式
Action Uri 必填

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

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

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

字符串

推荐文本大小:最多50个字符

个人资料 - 头像 必填

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

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

请参阅图片规格以获得指导。
个人资料 - 附加文本 可选 自由文本,例如个人资料用户名。

自由文本

推荐文本大小:最多15个字符

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

提供多张图片时,我们只会显示一张图片。推荐宽高比为16:9。

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

请参阅图片规格以获得指导。
流行度 - 计数 可选

指示关注者数量或流行度值,例如“370万”。

注意:如果同时提供计数和计数值,则使用计数。

字符串

推荐文本大小:计数+标签组合最多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

属性 要求 描述 格式
Action Uri 必填

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

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

Uri
标题 必填 实体的标题。

字符串

推荐文本大小:最多50个字符

开始时间 必填

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

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

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

一个字段,用于指示活动将是虚拟的、线下的还是两者兼而有之。

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

提供多张图片时,我们只会显示一张图片。推荐宽高比为16:9。

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

请参阅图片规格以获得指导。
位置 - 国家/地区 条件必填

活动举办的国家/地区。

注意:对于IN_PERSON或HYBRID活动,这是必需的。

自由文本

推荐文本大小:最多约20个字符

位置 - 城市 条件必填

活动举办的城市。

注意:对于IN_PERSON或HYBRID活动,这是必需的。

自由文本

推荐文本大小:最多约20个字符

位置 - 显示地址 条件必填

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

注意:对于IN_PERSON或HYBRID活动,这是必需的。

自由文本

推荐文本大小:最多约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

属性 要求 描述 格式
Action Uri 必填

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

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

Uri
标题 必填 实体的标题。

字符串

推荐文本大小:最多50个字符

开始时间 必填

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

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

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

一个字段,用于指示活动将是虚拟的、线下的还是两者兼而有之。

枚举:VIRTUAL、IN_PERSON或HYBRID
位置 - 国家/地区 条件必填

活动举办的国家/地区。

注意:对于IN_PERSON或HYBRID活动,这是必需的。

自由文本

推荐文本大小:最多约20个字符

位置 - 城市 条件必填

活动举办的城市。

注意:对于IN_PERSON或HYBRID活动,这是必需的。

自由文本

推荐文本大小:最多约20个字符

位置 - 显示地址 条件必填

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

注意:对于IN_PERSON或HYBRID活动,这是必需的。

自由文本

推荐文本大小:最多约20个字符

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

自由文本

推荐文本大小:最多约20个字符

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

自由文本

推荐文本大小:最多约20个字符

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

自由文本

推荐文本大小:最多约20个字符

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

自由文本

推荐文本大小:最多约20个字符

海报图片 可选

提供多张图片时,我们只会显示一张图片。推荐宽高比为16:9。

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

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

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

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

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

服务提供商的名称。

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

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

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

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

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

一段描述实体的文本。

注意:只会向用户显示描述或副标题列表,不会同时显示两者。

自由文本

推荐文本大小: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. 一些实体,例如ArticleEntityGenericFeaturedEntity,可以使用任何内容类别。对于其他实体,例如EventEntityEventReservationEntityPersonEntity,则只能使用这些类别中的子集。在填充列表之前,请检查某个实体类型适用的类别列表。
  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数据。
  • 解析请求中的数据并将其存储在更新后的Recommendation Cluster中。

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

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数据。
  • 解析请求中的数据并将其存储在更新后的Featured Cluster中。

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

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数据。
  • 解析请求中的数据并将其存储在更新后的Continuation Cluster中。

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

publishUserAccountManagementRequest

此API用于发布登录卡片。登录操作会将用户定向到应用的登录页面,以便应用可以发布内容(或提供更个性化的内容)。

以下元数据是登录卡片的一部分:

属性 要求 描述
Action 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返回,其中包含错误代码作为原因。

错误代码 错误名称 说明
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:处理广播意图

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

广播 Intent 的主要目的是重新激活应用并强制数据同步。广播 Intent 不应频繁发送。只有当 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>标签静态声明一个实现。这允许应用程序在未运行时接收广播 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 常见问题解答

联系方式

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

后续步骤

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

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