在用户所在平台覆盖他们,提高应用互动度。集成 Engage SDK,以便直接在收藏、Entertainment Space 和 Play 商店等多个设备端展示途径中,向用户推送个性化推荐和续播内容。集成后,平均 APK 的大小(压缩后)会增加不到 50 KB,并且大多数应用只需开发者花费大约一周的时间。如需了解详情,请访问我们的企业网站。
本指南包含面向开发者合作伙伴的说明,介绍了如何将食品内容(食品订购、食品或餐厅评价和发现、餐点订阅、食谱)提供给 Engage 内容平台。
集成详情
术语
此集成包括以下五类集群类型:推荐、精选、食品购物车、食品购物清单和重新订购。
- 推荐集群用于显示来自单个开发者合作伙伴的个性化食品相关建议。此类推荐既可以针对用户个性化定制,也可以一般化(例如,新品促销)。您可以根据自己的需要使用它们来显示食谱、商店、菜肴、杂货等内容。 - 推荐集群可以由 ProductEntity、StoreEntity或RecipeEntity列表组成,但不能由不同实体类型组合而成。
   - 图:`ProductEntity`、`StoreEntity` 和 `RecipeEntity`。(*界面仅作说明之用) 
- 推荐集群可以由 
- 精选集群用于在一个界面分组中展示来自多个开发者合作伙伴的精选实体。精选集群只有一个,并将显示在界面顶部附近,其展示位置的优先级高于所有推荐集群。每个开发者合作伙伴最多可以在精选集群中广播 10 个实体。   - 图:包含 `RecipeEntity` 的精选集群。 (*界面仅作说明之用) 
- 食品购物车集群用于在一个界面分组中显示来自多个开发者合作伙伴的杂货购物车预览,以提示用户完成购物车中的未付款交易。食品购物车集群只有一个。 - 食品购物车集群必须显示购物车中项的总数量,还可以包含用户购物车中 X 个项的图片。   - 图:来自单个合作伙伴的食品购物车集群。(*界面仅作说明之用) 
 
- 食品购物清单集群用于在一个界面分组中显示来自多个开发者合作伙伴的杂货购物清单预览,以提示用户返回相应应用更新清单并完成其中的购买交易。食品购物清单集群只有一个。   - 图:来自单个合作伙伴的食品购物清单集群。(*界面仅作说明之用) 
- 重新订购集群用于在一个界面分组中显示来自多个开发者合作伙伴的先前订单预览,以提示用户重新订购。 重新订购集群只有一个。 - 重新订购集群必须显示用户先前订单中项的总数量,并且还必须包含以下任一项: - 用户先前订单中的 X 个项的图片。
- 用户先前订单中的 X 个项的标签。
 
   - 图:来自单个合作伙伴的食品重新订购集群。(*界面仅作说明之用) 
准备工作
最低 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'
}
摘要
设计的前提是已实现了绑定服务。
对于不同的集群类型,客户端可以发布的数据受以下限制:
| 集群类型 | 集群限制 | 集群中的实体数上限 | 
|---|---|---|
| 推荐集群 | 最多 7 个 | 最多 50 个( ProductEntity、RecipeEntity或StoreEntity) | 
| 精选集群 | 最多 1 个 | 最多 20 个( ProductEntity、RecipeEntity或StoreEntity) | 
| 食品购物车集群 | 最多 1 个 | 最多 1 个 ShoppingCartEntity | 
| 食品购物清单集群 | 最多 1 个 | 最多 1 个 ShoppingListEntity | 
| 食品重新订购集群 | 最多 1 个 | 最多 1 个 ReorderEntity | 
第 1 步:提供实体数据
SDK 定义了不同的实体来代表每种内容类型。对于“Food”类别,我们支持下列实体:
- ProductEntity
- StoreEntity
- RecipeEntity
- FoodShoppingCart
- FoodShoppingList
- FoodReorderCluster
下面的图表列出了每种类型的可用属性和相关要求。
ProductEntity
ProductEntity 对象代表开发者合作伙伴想要发布的单个项(例如杂货商品、餐馆菜肴或促销)。
 
    ProductEntity 的属性
    | 属性 | 要求 | 说明 | 格式 | 
|---|---|---|---|
| 海报图片 | 必需 | 必须提供至少一张图片。 | 如需相关指导,请参阅图片规范。 | 
| 操作 URI | 必需 | 指向应用中用于显示相应商品详细信息的页面的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此常见问题解答 | URI | 
| 标题 | 可选 | 商品的名称。 | 自由文本 建议的文本大小:少于 90 个字符(如果文本过长,可能会显示省略号) | 
| 价格 - 当前 | 在特定条件下必需 | 商品的当前价格。 如果提供带删除线的价格,则必须提供。 | 自由文本 | 
| 价格 - 删除线 | 可选 | 实体的原始价格,在界面中带有删除线。 | 自由文本 | 
| 宣传信息 | 可选 | 用于展示商品的促销、活动或最新动态的宣传信息(如果有)。 | 自由文本 建议的文本大小:少于 45 个字符(如果文本过长,可能会显示省略号) | 
| 宣传信息附属细则 | 可选 | 宣传信息的附属细则文本。 | 自由文本 建议的文本大小:少于 45 个字符(如果文本过长,可能会显示省略号) | 
| 评分(可选)- 注意:所有评分都将依照我们的标准星级分级制度显示。 | |||
| 评分 - 最大值 | 可选 | 评分量表的最大值。 如果同时提供当前评分值,则必须提供。 | 数值 >= 0.0 | 
| 评分 - 当前值 | 可选 | 评分量表的当前值。 如果同时提供最大评分值,则必须提供。 | 数值 >= 0.0 | 
| 评分 - 数量 | 可选 | 商品的评分数量。 注意:如果您的应用控制向用户显示数量的方式,请提供此字段。使用简洁的字符串。 例如,如果数量为 1,000,000,请考虑使用 1M 等缩写,以免数量在较小的显示尺寸上被截断。 | 字符串 | 
| 评分 - 计数值 | 可选 | 商品的评分数量。 注意:如果您不自行处理显示缩写逻辑,请提供此字段。如果“数量”和“数量值”都存在,则向用户显示“数量”。 | 长 | 
| DisplayTimeWindow(可选)- 设置要在 surface 上显示的内容的时间范围 | |||
| 开始时间戳 | 可选 | 纪元时间戳,在其之后相应内容应显示在 surface 上。 如果未设置,相应内容将有资格显示在 surface 上。 | 纪元时间戳(以毫秒为单位) | 
| 结束时间戳 | 可选 | 纪元时间戳,在其之后相应内容不再显示在 surface 上。 如果未设置,相应内容将有资格显示在 surface 上。 | 纪元时间戳(以毫秒为单位) | 
StoreEntity
StoreEntity 对象代表开发者合作伙伴想要发布的单个商店,例如餐馆或杂货店。
 
    StoreEntity 的属性
    | 属性 | 要求 | 说明 | 格式 | 
|---|---|---|---|
| 海报图片 | 必需 | 必须提供至少一张图片。 | 如需相关指导,请参阅图片规范。 | 
| 操作 URI | 必需 | 指向应用中用于显示相应商店详细信息的页面的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此常见问题解答 | URI | 
| 标题 | 可选 | 商店的名称。 | 自由文本 建议的文本大小:少于 45 个字符(如果文本过长,可能会显示省略号) | 
| 位置 | 可选 | 商店的位置信息。 | 自由文本 建议的文本大小:少于 45 个字符(如果文本过长,可能会显示省略号) | 
| 宣传信息 | 可选 | 用于展示商店的促销、活动或最新动态的宣传信息(如果有)。 | 自由文本 建议的文本大小:少于 45 个字符(如果文本过长,可能会显示省略号) | 
| 宣传信息附属细则 | 可选 | 宣传信息的附属细则文本。 | 自由文本 建议的文本大小:少于 45 个字符(如果文本过长,可能会显示省略号) | 
| 说明 | 可选 | 商店的说明。 | 自由文本 建议的文本大小:少于 90 个字符(如果文本过长,可能会显示省略号) | 
| 类别 | 可选 | 商店的类别,在餐饮场所的背景下,可以是“法式”“新美式”“拉面”“精致餐饮”等美食。 | 自由文本 建议的文本大小:少于 45 个字符(如果文本过长,可能会显示省略号) | 
| 注意:所有评分都将依照我们的标准星级分级制度显示。 | |||
| 评分 - 最大值 | 可选 | 评分量表的最大值。 如果同时提供当前评分值,则必须提供。 | 数值 >= 0.0 | 
| 评分 - 当前值 | 可选 | 评分量表的当前值。 如果同时提供最大评分值,则必须提供。 | 数值 >= 0.0 | 
| 评分 - 数量 | 可选 | 商店评分的数量。 注意:如果您的应用想要控制此字段向用户的显示方式,请提供此字段。提供可向用户显示的简洁字符串。例如,如果数量为 1,000,000,请考虑使用 1M 等缩写形式,这样就不会在较小的显示尺寸上被截断。 | 字符串 | 
| 评分 - 计数值 | 可选 | 商店评分的数量。 注意:如果您不想自行处理显示缩写逻辑,请提供此字段。如果同时存在“数量”和“数量值”,我们将使用“数量”向用户显示 | 长 | 
RecipeEntity
RecipeEntity 对象代表开发者合作伙伴想要发布的食谱项。
 
    RecipeEntity 的属性
    | 属性 | 要求 | 说明 | 格式 | 
|---|---|---|---|
| 海报图片 | 必需 | 必须提供至少一张图片。 | 如需相关指导,请参阅图片规范。 | 
| 操作 URI | 必需 | 指向应用中用于显示相应食谱详细信息的页面的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此常见问题解答 | URI | 
| 标题 | 可选 | 食谱的名称。 | 自由文本 建议的文本大小:少于 45 个字符(如果文本过长,可能会显示省略号) | 
| 作者 | 可选 | 食谱的作者。 | 自由文本 建议的文本大小:少于 45 个字符(如果文本过长,可能会显示省略号) | 
| 烹饪/准备时间 | 可选 | 食谱的烹饪时间。 | 自由文本 建议的文本大小:少于 45 个字符(如果文本过长,可能会显示省略号) | 
| 宣传信息 | 可选 | 用于展示食谱的促销、活动或最新动态的宣传信息(如果有)。 | 自由文本 建议的文本大小:少于 45 个字符(如果文本过长,可能会显示省略号) | 
| 类别 | 可选 | 食谱的类别。 | 自由文本 建议的文本大小:少于 45 个字符(如果文本过长,可能会显示省略号) | 
| 说明 | 可选 | 食谱的说明。 | 自由文本 建议的文本大小:少于 90 个字符(如果文本过长,可能会显示省略号) | 
| 注意:所有评分都将依照我们的标准星级分级制度显示。 | |||
| 评分 - 最大值 | 可选 | 评分量表的最大值。 如果同时提供当前评分值,则必须提供。 | 数值 >= 0.0 | 
| 评分 - 当前值 | 可选 | 评分量表的当前值。 如果同时提供最大评分值,则必须提供。 | 数值 >= 0.0 | 
| 评分 - 数量 | 可选 | 食谱的评分数量。 注意:如果您的应用想要控制此字段向用户的显示方式,请提供此字段。提供可向用户显示的简洁字符串。例如,如果数量为 1,000,000,请考虑使用 1M 等缩写形式,这样就不会在较小的显示尺寸上被截断。 | 字符串 | 
| 评分 - 计数值 | 可选 | 食谱的评分数量。 注意:如果您不想自行处理显示缩写逻辑,请提供此字段。如果同时存在“数量”和“数量值”,我们将使用“数量”向用户显示 | 长 | 
FoodShoppingCart
 
        | 属性 | 要求 | 说明 | 格式 | 
|---|---|---|---|
| 操作 URI | 必需 | 指向合作伙伴应用中的购物车的深层链接。 注意:您可以使用深层链接进行归因。 不妨参阅此处的常见问题解答 | URI | 
| 项数 | 必需 | 购物车中项的数量(而不仅仅是商品数量)。 例如:如果购物车中有 3 个橘子和 1 个苹果,则此数值应为 4。 | 整数 >= 1 | 
| 标题 | 可选 | 购物车的标题(例如“您的购物车”)。 如果开发者未提供标题,则使用默认标题“您的购物车”。 | 自由文本 建议的文本大小:少于 25 个字符(如果文本过长,可能会显示省略号) | 
| 操作文本 | 可选 | 购物车中相应按钮的号召性用语文本(例如您的购物袋)。 如果开发者未提供任何操作文本,系统将默认使用查看购物车。 此属性在 1.1.0 及更高版本中受支持。 | 字符串 | 
| 购物车图片 | 可选 | 购物车中每件商品的图片。 可按优先顺序提供最多 10 张图片;实际显示的图片数量取决于设备的外形规格。 | 如需相关指导,请参阅图片规范。 | 
| 项标签 | 可选 | 购物清单中项的标签列表。 实际显示的标签数量取决于设备的外形规格。 | 自由文本标签列表 建议的文本大小:少于 20 个字符(如果文本过长,可能会显示省略号) | 
| DisplayTimeWindow(可选)- 设置要在 surface 上显示的内容的时间范围 | |||
| 开始时间戳 | 可选 | 纪元时间戳,在其之后相应内容应显示在 surface 上。 如果未设置,相应内容将有资格显示在 surface 上。 | 纪元时间戳(以毫秒为单位) | 
| 结束时间戳 | 可选 | 纪元时间戳,在其之后相应内容不再显示在 surface 上。 如果未设置,相应内容将有资格显示在 surface 上。 | 纪元时间戳(以毫秒为单位) | 
FoodShoppingList
 
        | 属性 | 要求 | 说明 | 格式 | 
|---|---|---|---|
| 操作 URI | 必需 | 指向合作伙伴应用中的购物清单的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此常见问题解答 | URI | 
| 项数 | 必需 | 购物清单中项的数量。 | 整数 >= 1 | 
| 标题 | 可选 | 列表的标题(例如“您的购物清单”)。 如果开发者未提供标题,则使用默认标题“购物清单”。 | 自由文本 建议的文本大小:少于 25 个字符(如果文本过长,可能会显示省略号) | 
| 项标签 | 必需 | 购物清单中项的标签列表。 必须提供至少 1 个标签,并且可按优先顺序提供最多 10 个标签;实际显示的图片数量取决于设备的外形规格。 | 自由文本标签列表 建议的文本大小:少于 20 个字符(如果文本过长,可能会显示省略号) | 
FoodReorderCluster
 
        | 属性 | 要求 | 说明 | 格式 | 
|---|---|---|---|
| 操作 URI | 必需 | 指向合作伙伴应用中的重新订购部分的深层链接。 注意:您可以使用深层链接进行归因。 请参阅此常见问题解答 | URI | 
| 操作文本 | 可选 | 重新订购部分上相应按钮的号召性用语文本(例如,“重新订购”)。 如果开发者未提供任何操作文本,系统将默认使用“重新订购”。 此属性在 1.1.0 及更高版本中受支持。 | 字符串 | 
| 项数 | 必需 | 先前订单中商品的数量(而不仅仅是商品数量)。 例如:如果先前订单中有 3 小杯咖啡和 1 个羊角面包,则此数值应为 4。 | 整数 >= 1 | 
| 标题 | 必需 | 重新订购项的标题。 | 自由文本 建议的文本大小:少于 40 个字符(如果文本过长,可能会显示省略号) | 
| 项标签 | 可选 (如未提供,则应提供海报图片) | 先前订单的项标签列表。 可按优先顺序提供最多 10 个标签;实际显示的标签数量取决于设备的外形规格。 | 自由文本列表 每个标签建议的文本大小:少于 20 个字符(如果文本过长,可能会显示省略号) | 
| 海报图片 | 可选 (如未提供,则应提供项标签) | 先前订单中项的图片。 可按优先顺序提供最多 10 张图片;实际显示的图片数量取决于设备的外形规格。 | 如需相关指导,请参阅图片规范。 | 
图片规范
下面列出了图片资源必须遵循的规范:
| 宽高比 | 最小像素 | 建议的像素 | 
|---|---|---|
| 方形 (1x1) 首选 | 300x300 | 1200x1200 | 
| 横向 (1.91x1) | 600x314 | 1200x628 | 
| 纵向 (4x5) | 480x600 | 960x1200 | 
文件格式
PNG、JPG、静态 GIF、WebP
文件大小上限
5120 KB
其他建议
- 图片安全区域:将重要内容放在图片中间 80% 的区域内。
- 请使用透明背景,以便图片可在“深色主题”和“浅色主题”设置中正常显示。
第 2 步:提供集群数据
建议在后台执行内容发布作业(例如,使用 WorkManager),并安排定期执行或按事件执行(例如,每当用户打开应用时,或当用户刚刚将商品添加到购物车时)。
AppEngageFoodClient 负责发布食品集群。
以下 API 可用于在客户端中发布集群:
- isServiceAvailable
- publishRecommendationClusters
- publishFeaturedCluster
- publishFoodShoppingCart
- publishFoodShoppingList
- publishReorderCluster
- publishUserAccountManagementRequest
- updatePublishStatus
- deleteRecommendationsClusters
- deleteFeaturedCluster
- deleteFoodShoppingCartCluster
- deleteFoodShoppingListCluster
- deleteReorderCluster
- 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 对象列表。
RecommendationCluster 对象可以具有以下属性:
| 属性 | 要求 | 说明 | 
|---|---|---|
| ProductEntity、StoreEntity 或 RecipeEntity 列表 | 必需 | 构成此推荐集群的推荐的实体列表。单个集群中的实体必须属于同一类型。 | 
| 标题 | 必需 | 推荐集群的标题(例如“感恩节菜单超值立省”)。 建议的文本大小:少于 25 个字符(如果文本过长,可能会显示省略号) | 
| 副标题 | 可选 | 推荐集群的副标题。 | 
| 操作 URI | 可选 | 指向合作伙伴应用中向用户显示完整推荐列表的页面的深层链接。 注意:您可以使用深层链接进行归因。 不妨参阅此处的常见问题解答 | 
Kotlin
client.publishRecommendationClusters(
            PublishRecommendationClustersRequest.Builder()
                .addRecommendationCluster(
                    RecommendationCluster.Builder()
                        .addEntity(entity1)
                        .addEntity(entity2)
                        .setTitle("Big savings on Thanksgiving menu")
                        .build())
                .build())
Java
client.publishRecommendationClusters(
            new PublishRecommendationClustersRequest.Builder()
                .addRecommendationCluster(
                    new RecommendationCluster.Builder()
                        .addEntity(entity1)
                        .addEntity(entity2)
                        .setTitle("Big savings on Thanksgiving menu")
                        .build())
                .build());
当服务收到请求时,系统会在一项事务中执行以下操作:
- 系统会移除所有现有的推荐集群数据。
- 系统会解析请求中的数据,并将其存储在新的推荐集群中。
如果发生错误,系统将拒绝整个请求,并保留现有状态。
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数据。
- 系统会解析请求中的数据,并将其存储在经过更新的精选集群中。
如果发生错误,系统将拒绝整个请求,并保留现有状态。
publishFoodShoppingCart
此 API 用于发布 FoodShoppingCart 对象。
Kotlin
client.publishFoodShoppingCart(
            PublishFoodShoppingCartClusterRequest.Builder()
                .setShoppingCart(
                    FoodShoppingCart.Builder()
                        ...
                        .build())
                .build())
Java
client.publishFoodShoppingCart(
            new PublishFoodShoppingCartClusterRequest.Builder()
                .setShoppingCart(
                    new FoodShoppingCart.Builder()
                        ...
                        .build())
                .build());
当服务收到请求时,系统会在一项事务中执行以下操作:
- 系统会移除开发者合作伙伴的现有 FoodShoppingCart数据。
- 系统会解析请求中的数据,并将其存储在经过更新的购物车集群中。
如果发生错误,系统将拒绝整个请求,并保留现有状态。
publishFoodShoppingList
此 API 用于发布 FoodShoppingList 对象。
Kotlin
client.publishFoodShoppingList(
            PublishFoodShoppingListRequest.Builder()
                .setFoodShoppingList(
                    FoodShoppingListEntity.Builder()
                        ...
                        .build())
                .build())
Java
client.publishFoodShoppingList(
            new PublishFoodShoppingListRequest.Builder()
                .setFoodShoppingList(
                    new FoodShoppingListEntity.Builder()
                        ...
                        .build())
                .build());
当服务收到请求时,系统会在一项事务中执行以下操作:
- 系统会移除开发者合作伙伴的现有 FoodShoppingList数据。
- 系统会解析请求中的数据,并将其存储在经过更新的购物清单集群中。
如果发生错误,系统将拒绝整个请求,并保留现有状态。
publishReorderCluster
此 API 用于发布 FoodReorderCluster 对象。
Kotlin
client.publishReorderCluster(
            PublishReorderClusterRequest.Builder()
                .setReorderCluster(
                    FoodReorderCluster.Builder()
                        ...
                        .build())
                .build())
Java
client.publishReorderCluster(
            new PublishReorderClusterRequest.Builder()
                .setReorderCluster(
                    new FoodReorderCluster.Builder()
                        ...
                        .build())
                .build());
当服务收到请求时,系统会在一项事务中执行以下操作:
- 系统会移除开发者合作伙伴的现有 FoodReorderCluster数据。
- 系统会解析请求中的数据,并将其存储在经过更新的重新订购集群中。
如果发生错误,系统将拒绝整个请求,并保留现有状态。
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 会从精选集群中移除现有数据。如果发生错误,系统将拒绝整个请求,并保留现有状态。
deleteFoodShoppingCartCluster
此 API 用于删除食品购物车集群的内容。
Kotlin
client.deleteFoodShoppingCartCluster()
Java
client.deleteFoodShoppingCartCluster();
当服务收到请求时,此 API 会从食品购物车集群中移除现有数据。如果发生错误,系统将拒绝整个请求,并保留现有状态。
deleteFoodShoppingListCluster
此 API 用于删除食品购物清单集群的内容。
Kotlin
client.deleteFoodShoppingListCluster()
Java
client.deleteFoodShoppingListCluster();
当服务收到请求时,此 API 会从食品购物清单集群中移除现有数据。如果发生错误,系统将拒绝整个请求,并保留现有状态。
deleteReorderCluster
此 API 用于删除 FoodReorderCluster 的内容。
Kotlin
client.deleteReorderCluster()
Java
client.deleteReorderCluster();
当服务收到请求时,此 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类的实例。这样一来,仍位于内存中的应用即可进行通信。
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 food shopping cart cluster publish when PUBLISH_FOOD_SHOPPING_CART broadcast
  // is received
  // Trigger food shopping list cluster publish when PUBLISH_FOOD_SHOPPING_LIST broadcast
  // is received
  // Trigger reorder cluster publish when PUBLISH_REORDER_CLUSTER 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 food Shopping Cart Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_FOOD_SHOPPING_CART),
                           com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                           /*scheduler=*/null)
// Register food Shopping List Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_FOOD_SHOPPING_LIST),
                           com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                           /*scheduler=*/null)
// Register Reorder Cluster Publish Intent
  context.registerReceiver(AppEngageBroadcastReceiver(),
                           IntentFilter(Intents.ACTION_PUBLISH_REORDER_CLUSTER),
                           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 food shopping cart cluster publish when PUBLISH_FOOD_SHOPPING_CART broadcast is
// received
// Trigger food shopping list cluster publish when PUBLISH_FOOD_SHOPPING_LIST broadcast is
// received
// Trigger reorder cluster publish when PUBLISH_REORDER_CLUSTER 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 food Shopping Cart Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
                         new IntentFilter(com.google.android.engage.shopping.service.Intents.ACTION_PUBLISH_FOOD_SHOPPING_CART),
                         com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                         /*scheduler=*/null);
// Register food Shopping List Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
                         new IntentFilter(com.google.android.engage.shopping.service.Intents.ACTION_PUBLISH_FOOD_SHOPPING_LIST),
                         com.google.android.engage.service.BroadcastReceiverPermissions.BROADCAST_REQUEST_DATA_PUBLISH_PERMISSION,
                         /*scheduler=*/null);
// Register Reorder Cluster Publish Intent
context.registerReceiver(new AppEngageBroadcastReceiver(),
                         new IntentFilter(com.google.android.engage.shopping.service.Intents.ACTION_PUBLISH_REORDER_CLUSTER),
                         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.food.PUBLISH_FOOD_SHOPPING_CART" />
      </intent-filter>
      <intent-filter>
         <action android:name="com.google.android.engage.action.food.PUBLISH_FOOD_SHOPPING_LIST" />
      </intent-filter>
      <intent-filter>
         <action android:name="com.google.android.engage.action.food.PUBLISH_REORDER_CLUSTER" />
      </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.food.PUBLISH_FOOD_SHOPPING_CART建议在收到此 intent 时启动- publishFoodShoppingCart调用。
- com.google.android.engage.action.food.PUBLISH_FOOD_SHOPPING_LIST建议在收到此 intent 时启动- publishFoodShoppingList调用。
- com.google.android.engage.action.food.PUBLISH_REORDER_CLUSTER建议在收到此 intent 时启动- publishReorderCluster调用。
集成工作流
如需查看在集成完成后验证集成的分步指南,请参阅 Engage 开发者集成工作流程。
常见问题解答
如需查看常见问题解答,请参阅 Engage SDK 常见问题解答。
联系人
如果在集成过程中有任何疑问,请与 engage-developers@google.com 联系。我们的团队会尽快回复您。
后续步骤
完成此集成后,请执行下列后续步骤:
- 发送电子邮件至 engage-developers@google.com,并将可供 Google 测试的集成 APK 添加为附件。
- Google 将在内部执行验证和审核,以确保集成可按预期运行。如果需要进行更改,Google 将与您联系,告知您任何必要的详细信息。
- 测试完成,如果无需进行任何更改,Google 将与您联系,以向您说明您已可以开始将经过更新的集成 APK 发布到 Play 商店。
- 在 Google 确认经过更新的 APK 已发布到 Play 商店后,您的推荐、精选、购物车、购物清单和重新订购集群便会发布并向用户显示。
