Engage SDK Social:第三方技术集成说明

Google 将打造一种设备端 surface,该 surface 可按行业整理用户的应用,并且支持全新的沉浸式体验,使用户能够以个性化的方式消费和发现应用内容。这种全屏体验使开发者合作伙伴有机会在其应用之外的专门频道中展示自己最棒的富媒体内容。

本文档包含面向开发者合作伙伴的说明,以协助其使用 Engage SDK 集成社交内容来填充这一新 surface 区域。

集成详情

以下部分介绍了集成详情。

术语

推荐集群用于显示来自单个开发者合作伙伴的个性化推荐。

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

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

每个推荐集群都由以下两类实体之一组成:

  • PortraitMediaEntity
  • SocialPostEntity

PortraitMediaEntity 必须包含帖子的 1 张纵向图片,可选择提供与个人资料和互动相关的元数据。

  • 帖子

    • 纵向图片和时间戳,或者
    • 纵向图片 + 文字内容和时间戳
  • 个人资料

    • 头像、姓名或标识名、附加图片
  • 互动

    • 仅计数和标签,或者
    • 计数和视觉内容(图标)

SocialPostEntity 包含与个人资料、帖子和互动相关的元数据。

  • 个人资料

    • 头像、姓名或标识名、附加文字、附加图片
  • 帖子

    • 文字和时间戳,或
    • 富媒体(图片或富媒体网址)和时间戳,或者
    • 文字和富媒体(图片或富媒体网址)及时间戳,或者
    • 视频预览(缩略图和时长)和时间戳
  • 互动

    • 仅计数和标签,或者
    • 计数和视觉内容(图标)

准备工作

最低 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 个(PortraitMediaEntitySocialPostEntity 最多 25 个(PortraitMediaEntitySocialPostEntity

第 1 步:提供实体数据

SDK 定义了不同的实体来代表每种内容类型。对于“社交”类别,SDK 支持以下实体:

  1. PortraitMediaEntity
  2. SocialPostEntity

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

PortraitMediaEntity

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

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

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

URI
与帖子相关的元数据(必需)
图片 必需

图片应采用纵向宽高比

如果提供了多张图片,界面可能只会显示 1 张图片。不过,界面可能会直观地表明应用中有更多图片。

如果帖子内容是视频,提供商应提供要显示为图片的视频缩略图。

如需相关指导,请参阅图片规范
文字内容 可选 帖子、动态等内容的主要文字。 字符串(建议不超过 140 个字符)
时间戳 可选 帖子的发布时间。 纪元时间戳(以毫秒为单位)
是视频内容 可选 帖子是视频吗? 布尔值
视频时长 可选 视频的时长(以毫秒为单位)。
与个人资料相关的元数据(可选)
名称 必需 个人资料名称、ID 或标识名(例如“John Doe”“@TeamPixel”) 字符串(建议不超过 25 个字符)
头像 必需

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

方形 1:1 图片

如需相关指导,请参阅图片规范
附加图片 可选

个人资料徽章,例如验证徽章

方形 1:1 图片

如需相关指导,请参阅图片规范
与互动相关的元数据(可选)
计数 可选

表明互动次数,例如“370 万”。

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

字符串

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

计数值 可选

互动次数(值)。

注意:如果您的应用未处理有关如何针对不同显示大小优化大数字的逻辑,请提供“Count Value”(计数值)而非“Count”(计数)。如果同时提供了“计数”和“计数值”,系统会使用“计数”。

标签 可选 指明互动标签的用途。例如,“点赞”。

字符串

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

视觉内容 可选

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

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

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

如需相关指导,请参阅图片规范
DisplayTimeWindow(可选)- 设置要在 surface 上显示的内容的时间范围
开始时间戳 可选

纪元时间戳,在其之后相应内容应显示在 surface 上。

如果未设置,相应内容将有资格显示在 surface 上。

纪元时间戳(以毫秒为单位)
结束时间戳 可选

纪元时间戳,在其之后相应内容不再显示在 surface 上。

如果未设置,相应内容将有资格显示在 surface 上。

纪元时间戳(以毫秒为单位)

SocialPostEntity

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

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

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

URI

与帖子相关的元数据(必需)

至少需要 TextContent、Image 或 WebContent 三者之一

图片 可选

图片应采用纵向宽高比

如果提供了多张图片,界面可能只会显示 1 张图片。不过,界面可能会直观地表明应用中有更多图片。

如果帖子内容是视频,提供商应提供要显示为图片的视频缩略图。

如需相关指导,请参阅图片规范
文字内容 可选 帖子、动态等内容的主要文字。 字符串(建议不超过 140 个字符)
视频内容(可选)
时长 必需 视频的时长(以毫秒为单位)。
图片 必需 视频内容的预览图片。 如需相关指导,请参阅图片规范
链接预览(可选)
链接预览 - 标题 必需 用于指明网页内容标题的文字 字符串
链接预览 - 主机名 必需 用于指明网页所有者的文字,例如“INSIDER” 字符串
链接预览 - 图片 可选 网页内容的主打图片 如需相关指导,请参阅图片规范
时间戳 可选 帖子的发布时间。 纪元时间戳(以毫秒为单位)
与个人资料相关的元数据(可选)
名称 必需 个人资料名称、ID 或标识名(例如“John Doe”“@TeamPixel”)。 字符串(建议不超过 25 个字符)
附加文字 可选

可用作个人资料 ID、标识名或其他元数据

例如“@John-Doe”“500 万关注者”“你可能会喜欢”“时下流行”“5 个新帖子”

字符串(建议不超过 40 个字符)
头像 必需

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

方形 1:1 图片

如需相关指导,请参阅图片规范
附加图片 可选

个人资料徽章,例如验证徽章

方形 1:1 图片

如需相关指导,请参阅图片规范
与互动相关的元数据(可选)
计数 必需 表明互动次数,例如“370 万”。 字符串(计数 + 标签总计建议不超过 20 个字符)
标签

可选

如果未提供,必须提供视觉内容

表明互动的目的,例如“点赞”。 字符串(计数 + 标签总计建议不超过 20 个字符)
视觉内容

可选

如果未提供,必须提供标签

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

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

方形 1:1 图片

如需相关指导,请参阅图片规范
DisplayTimeWindow(可选)- 设置要在 surface 上显示的内容的时间范围
开始时间戳 可选

纪元时间戳,在其之后相应内容应显示在 surface 上。

如果未设置,相应内容将有资格显示在 surface 上。

纪元时间戳(以毫秒为单位)
结束时间戳 可选

纪元时间戳,在其之后相应内容不再显示在 surface 上。

如果未设置,相应内容将有资格显示在 surface 上。

纪元时间戳(以毫秒为单位)

图片规范

图片必须托管在公共 CDN 上,以便 Google 可以访问。

文件格式

PNG、JPG、静态 GIF、WebP

文件大小上限

5120 KB

其他建议

  • 图片安全区域:将重要内容放在图片中间 80% 的区域内。
  • 请使用透明背景,以便图片可在“深色主题”和“浅色主题”设置中正常显示。

第 2 步:提供集群数据

建议在后台执行内容发布作业(例如,使用 WorkManager),并安排定期或按事件执行此类作业(例如,每当用户打开应用时,或当用户刚刚关注一个新账号时)

AppEngageSocialClient 负责发布社交集群。

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

  • isServiceAvailable
  • publishRecommendationClusters
  • publishUserAccountManagementRequest
  • updatePublishStatus
  • deleteRecommendationsClusters
  • 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 对象可以具有以下属性:

属性 要求 说明
SocialPostEntity 或 PortraitMediaEntity 列表 必需 构成此推荐集群的推荐的实体列表。单个集群中的实体必须属于同一类型。
标题 必需

推荐集群的标题(例如,“好友的最新动态”)。

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

副标题 可选 推荐集群的副标题。
操作 URI 可选

指向合作伙伴应用中向用户显示完整推荐列表的页面的深层链接。

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

Kotlin

client.publishRecommendationClusters(
            PublishRecommendationClustersRequest.Builder()
                .addRecommendationCluster(
                    RecommendationCluster.Builder()
                        .addEntity(entity1)
                        .addEntity(entity2)
                        .setTitle("Latest from your friends")
                        .build())
                .build())

Java

client.publishRecommendationClusters(
            new PublishRecommendationClustersRequest.Builder()
                .addRecommendationCluster(
                    new RecommendationCluster.Builder()
                        .addEntity(entity1)
                        .addEntity(entity2)
                        .setTitle("Latest from your friends")
                        .build())
                .build());

当服务收到请求时,系统会在一项事务中执行以下操作:

  • 系统会移除所有现有的推荐集群数据。
  • 系统会解析请求中的数据,并将其存储在新的推荐集群中。

如果发生错误,系统将拒绝整个请求,并保留现有状态。

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 会从建议集群中移除现有数据。如果发生错误,系统将拒绝整个请求,并保留现有状态。

deleteUserManagementCluster

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

Kotlin

client.deleteUserManagementCluster()

Java

client.deleteUserManagementCluster();

当服务收到请求时,此 API 会从 UserAccountManagement 集群中移除现有数据。如果发生错误,系统将拒绝整个请求,并保留现有状态。

deleteClusters

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

Kotlin

client.deleteClusters(
    DeleteClustersRequest.Builder()
      .addClusterType(ClusterType.TYPE_RECOMMENDATION)
      ...
      .build())

Java

client.deleteClusters(
            new DeleteClustersRequest.Builder()
                .addClusterType(ClusterType.TYPE_RECOMMENDATION)
                ...
                .build());

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

错误处理

强烈建议开发者监听来自发布 API 的任务结果,以便执行后续操作,从而恢复并重新提交成功的任务。

client.publishRecommendationClusters(
              new PublishRecommendationClustersRequest.Builder()
                  .addRecommendationCluster(...)
                  .build())
          .addOnCompleteListener(
              task -> {
                if (task.isSuccessful()) {
                  // do something
                } else {
                  Exception exception = task.getException();
                  if (exception instanceof AppEngageException) {
                    @AppEngageErrorCode
                    int errorCode = ((AppEngageException) exception).getErrorCode();
                    if (errorCode == AppEngageErrorCode.SERVICE_NOT_FOUND) {
                      // do something
                    }
                  }
                }
              });

系统将以 AppEngageException 的形式返回错误,相应原因将作为错误代码包含在内。

错误代码 错误名称 备注
1 SERVICE_NOT_FOUND 服务在给定设备上不可用。
2 SERVICE_NOT_AVAILABLE 服务在给定设备上可用,但在调用时不可用(例如,服务已被明确停用)。
3 SERVICE_CALL_EXECUTION_FAILURE 任务执行因线程问题而失败。在这种情况下,可以重试。
4 SERVICE_CALL_PERMISSION_DENIED 不允许调用方进行服务调用。
5 SERVICE_CALL_INVALID_ARGUMENT 请求包含无效数据(例如,集群数量超过允许的上限)。
6 SERVICE_CALL_INTERNAL 服务端出现错误。
7 SERVICE_CALL_RESOURCE_EXHAUSTED 服务调用过于频繁。

第 3 步:处理广播 intent

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

广播 intent 主要用于重新激活应用和强制同步数据。不应过于频繁地发送广播 intent。仅在 Engage Service 确定内容可能已过时(例如,内容是一周前的)的情况下,广播 intent 才会触发。这样一来,开发者将更加确信,即使应用长时间未执行,用户也能够获得新鲜的内容体验。

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

  • 使用 Context.registerReceiver() 动态注册 BroadcastReceiver 类的实例。这样一来,仍位于内存中的应用即可进行通信。
class AppEngageBroadcastReceiver extends BroadcastReceiver {
// Trigger recommendation cluster publish when PUBLISH_RECOMMENDATION broadcast
// is received
}

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

}

  • 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>
   </receiver>
</application>

服务将发送以下 intent

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

集成工作流程

如需查看在集成完成后验证集成的分步指南,请参阅 Engage 开发者集成工作流程

常见问题解答

如需查看常见问题解答,请参阅 Engage SDK 常见问题解答

联系人

如果在集成过程中有任何疑问,请与 engage-developers@google.com 联系。我们的团队会尽快回复您。

后续步骤

完成此集成后,请执行下列后续步骤:

  • 发送电子邮件至 engage-developers@google.com,并将可供 Google 测试的集成 APK 添加为附件。
  • Google 会执行验证,并在内部进行审核,以确保集成按预期运行。如果需要更改,Google 会与您联系,将所有必要的详细信息告知您。
  • 测试完毕后,如果无需进行任何更改,Google 将与您联系,向您说明您已可以开始将经过更新的集成 APK 发布到 Play 商店。
  • 在 Google 确认经过更新的 APK 已发布到 Play 商店后,您的推荐,集群便可被发布并向用户显示。