

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 使用 Amazon SNS 发送移动推送通知
<a name="mobile-push-notifications"></a>

 本部分描述如何发送移动推送通知消息。

## 向主题发布
<a name="mobile-push-send-topicmobile"></a>

您还可以使用 Amazon SNS 向订阅了某一主题的移动终端节点发送消息。其概念与订阅其他终端节点类型（如 Amazon SQS、HTTP/S、电子邮件和 SMS）相同，如 [什么是 Amazon SNS？](welcome.md) 中所述。不同之处在于，Amazon SNS 通过 Apple Push Notification Service (APNS) 和 Google Firebase Cloud Messaging (FCM) 等通知服务进行通信。通过通知服务通信，订阅的移动端点可以接收发送给相应主题的通知。

## 直接 Amazon SNS 移动设备消息传递
<a name="mobile-push-send-directmobile"></a>

您可以将 Amazon SNS 推送通知消息直接发送到代表移动设备上的应用程序的端点。

**发送直送消息**

1. 登录 [Amazon SNS 控制台](https://console.aws.amazon.com/sns/home)。

1. 在导航面板中，选择 **Push notifications**（推送通知）。

1. 例如，在**移动推送通知**页面的**平台应用程序**部分，选择应用程序的名称***MyApp***。

1. 在该***MyApp***页面的**终端节点**部分，选择终端节点，然后选择**发布消息**。

1. 在 **Publish message to endpoint (向终端节点发布消息)** 页面上，输入将显示在移动设备上的应用程序中的消息，然后选择**发布消息**。

   Amazon SNS 将通知消息发送到平台通知服务，而平台通知服务会将该消息发送到应用程序。

# 使用特定于平台的有效载荷发布 Amazon SNS 通知
<a name="sns-send-custom-platform-specific-payloads-mobile-devices"></a>

您可以使用 AWS 管理控制台 或 Amazon SNS APIs 向移动设备发送包含特定平台负载的自定义消息。有关使用 Amazon SNS 的信息 APIs，请参阅[移动推送 API 操作](mobile-push-api.md)和中的`SNSMobilePush.java`文件。`[snsmobilepush.zip](samples/snsmobilepush.zip)`

## 发送 JSON 格式化的消息
<a name="mobile-push-send-json"></a>

在发送平台特定的负载时，数据必须格式化为 JSON 键-值对字符串（用引号进行转义）。

下面的示例显示 FCM 平台的一条自定义消息。

```
{
"GCM": "{\"fcmV1Message\": {\"message\": {\"notification\": {\"title\": \"Hello\", \"body\": \"This is a test.\"}, \"data\": {\"dataKey\": \"example\"}}}}"
}
```

## 发送平台特定的消息
<a name="mobile-push-send-platform"></a>

除了以键-值对形式发送自定义数据之外，您还可以发送平台特定的键-值对。

以下示例显示如何在 FCM `data` 参数中的自定义数据键-值对之后加入 FCM 参数 `time_to_live` 和 `collapse_key`。

```
{
"GCM": "{\"fcmV1Message\": {\"message\": {\"notification\": {\"title\": \"TitleTest\", \"body\": \"Sample message for Android or iOS endpoints.\"}, \"data\":{\"time_to_live\": 3600,\"collapse_key\":\"deals\"}}}}"
}
```

有关 Amazon SNS 中支持的每个推送通知服务所支持的键-值对列表，请参阅以下内容：

**重要**  
Amazon SNS 现在支持 Firebase Cloud Messaging（FCM）HTTP v1 API，用于向 Android 设备发送移动推送通知。  
2024 年 3 月 26 日 – Amazon SNS 支持适用于 Apple 设备和 Webpush 目的地的 FCM HTTP v1 API。我们建议您在 2024 年 6 月 1 日或之前将现有的移动推送应用程序迁移到最新的 FCM HTTP v1 API，以避免应用程序中断。
+  APNs 文档中的@@ [有效载荷密钥参考](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/PayloadKeyReference.html#/apple_ref/doc/uid/TP40008194-CH17-SW1)
+ FCM 文档中的 [Firebase 云消息收发 HTTP 协议](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages)
+ ADM 文档中的[发送消息](https://developer.amazon.com/sdk/adm/sending-message.html)

## 在多个平台上向应用程序发送消息
<a name="mobile-push-send-multiplatform"></a>

要向安装在多个平台（例如 FCM 和）设备上的应用程序发送消息 APNs，您必须先在移动终端节点上订阅 Amazon SNS 中的主题，然后将消息发布到该主题。

以下示例显示了向 FCM 和 ADM 上 APNs订阅的移动终端节点发送的消息：

```
{ 
  "default": "This is the default message which must be present when publishing a message to a topic. The default message will only be used if a message is not present for 
one of the notification platforms.",     
  "APNS": "{\"aps\":{\"alert\": \"Check out these awesome deals!\",\"url\":\"www.amazon.com\"} }",
  "GCM": "{\"data\":{\"message\":\"Check out these awesome deals!\",\"url\":\"www.amazon.com\"}}",
  "ADM": "{\"data\":{\"message\":\"Check out these awesome deals!\",\"url\":\"www.amazon.com\"}}" 
}
```

## 将消息 APNs 作为警报或后台通知发送到
<a name="mobile-push-send-message-apns-background-notification"></a>

Amazon SNS 可以向广告 APNs 发送消息`alert`或`background`通知（有关更多信息，请参阅 APNs 文档中的[将后台更新推送到您的应用程序](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app)）。
+ `alert` APNs 通知通过显示警报消息、播放声音或在应用程序的图标上添加徽章来通知用户。
+ `background` APNs 通知会被唤醒或指示您的应用程序根据通知的内容采取行动，而不通知用户。

### 指定自定义 APNs 标题值
<a name="specify-custom-header-value"></a>

我们建议使用 Amazon SNS `Publish` API 操作为`AWS.SNS.MOBILE.APNS.PUSH_TYPE`[保留消息属性](sns-message-attributes.md#sns-attrib-mobile-reserved)指定自定义值 AWS SDKs，或。 AWS CLI以下 CLI 示例为指定的主题将 `content-available` 设置为 `1` 并将 `apns-push-type` 设置为 `background`。

```
aws sns publish \
--endpoint-url https://sns.us-east-1.amazonaws.com \
--target-arn arn:aws:sns:us-east-1:123456789012:endpoint/APNS_PLATFORM/MYAPP/1234a567-bc89-012d-3e45-6fg7h890123i \
--message '{"APNS_PLATFORM":"{\"aps\":{\"content-available\":1}}"}' \
--message-attributes '{ \
  "AWS.SNS.MOBILE.APNS.TOPIC":{"DataType":"String","StringValue":"com.amazon.mobile.messaging.myapp"}, \
  "AWS.SNS.MOBILE.APNS.PUSH_TYPE":{"DataType":"String","StringValue":"background"}, \
  "AWS.SNS.MOBILE.APNS.PRIORITY":{"DataType":"String","StringValue":"5"}}' \
--message-structure json
```

**注意**  
确保 JSON 结构有效。在每个键/值对（最后一个除外）后面添加一个逗号。

### 根据有效载荷 APNs 推断推送类型标头
<a name="inferring-push-type-header-from-payload"></a>

如果您未设置`apns-push-type` APNs 标头，Amazon SNS 会`background`根据您的 JSON 格式的负载 APNs 配置`aps`字典中的`content-available`密钥将标头设置为`alert`或依据。

**注意**  
Amazon SNS 只能推断 `background` 或 `alert` 标头，尽管 `apns-push-type` 标头可以设置为其他值。
+ `apns-push-type` 设置为 `alert`
  + 如果 `aps` 字典包含设置为 `1` 的 `content-available` 和*一个或多个*触发用户交互的键。
  + 如果 `aps` 字典包含设置为 `0` 的 `content-available` *或*如果 `content-available` 密钥不存在。
  + 如果 `content-available` 键的值不是整数或布尔值。
+ `apns-push-type` 设置为 `background`
  + 如果 `aps` 字典*仅*包含设置为 `1` 的 `content-available` 且不包含触发用户交互的*其他键*。
**重要**  
如果 Amazon SNS 将原始配置对象 APNs 作为仅限后台的通知发送，则必须在字典中包含`content-available`设置为。`1` `aps`尽管您可以包含自定义键，但 `aps` 字典不得包含触发用户交互的任何键（例如，警报、徽章或声音）。

下面是一个示例原始配置对象。

```
{
  "APNS": "{\"aps\":{\"content-available\":1},\"Foo1\":\"Bar\",\"Foo2\":123}"
}
```

在本示例中，Amazon SNS 将消息的`apns-push-type` APNs 标头设置为。`background`当 Amazon SNS 检测到 `apn` 字典包含设置为 `1` 的 `content-available` 键—并且不包含任何其他可触发用户交互的键时—它将标题设置为 `background`。

# 在 Amazon SNS 中使用 Google Firebase Cloud Messaging v1 有效载荷
<a name="sns-fcm-v1-payloads"></a>

Amazon SNS 支持使用 FCM HTTP v1 API 向 Android、iOS 和 Webpush 目标发送通知。本主题提供了使用 CLI 或 Amazon SNS API 发布移动推送通知时的有效载荷结构示例。

发送 FCM 通知时，您可以在有效载荷中包含以下消息类型：
+ **数据消息** - 数据消息由您的客户端应用程序处理，并包含自定义键值对。在构造数据消息时，必须包含以 JSON 对象作为值的 `data` 键，然后输入您的自定义键值对。
+ **通知消息**或**显示消息** - 通知消息包含由 FCM SDK 处理的一组预定义键。这些键因您要传送到的设备类型而异。有关特定于平台的通知键的更多信息，请参阅以下内容：
  + [Android 通知键](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages)
  + [APNS 通知键](https://developer.apple.com/documentation/usernotifications/generating-a-remote-notification)
  + [Webpush 通知键](https://developer.mozilla.org/en-US/docs/Web/API/Notification)

有关 FCM 消息类型的更多信息，请参阅 Google 的 *Firebase* 文档中的[消息类型](https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages)。

## 使用 FCM v1 有效载荷结构发送消息
<a name="sending-messages-using-v1-payload"></a>

如果您是首次创建 FCM 应用程序，或者希望利用 FCM v1 的功能，则可以选择发送 FCM v1 格式的有效载荷。为此，必须包含顶层键 `fcmV1Message`。*有关构建 FCM v1 有效负载的更多信息，请参阅 Google 的 Firebase 文档[中的从旧版 FCM 迁移 APIs 到 HTTP v1](https://firebase.google.com/docs/cloud-messaging/migrate-v1) 和[跨平台自定义消息](https://firebase.google.com/docs/cloud-messaging/concept-options#customizing-a-message-across-platforms)。*

**发送到 Amazon SNS 的 FCM v1 有效载荷示例：**

**注意**  
使用 Amazon SNS 发布通知时，以下示例中使用的 `GCM` 键值必须编码为字符串。

```
{
  "GCM": "{ 
    \"fcmV1Message\": { 
      \"validate_only\": false,
      \"message\": {
        \"notification\": {
          \"title\": \"string\",
          \"body\": \"string\"
        },
        \"data\": {
          \"dataGen\": \"priority message\"
        },
        \"android\": {
          \"priority\": \"high\",
          \"notification\": {
            \"body_loc_args\": [\"string\"],
            \"title_loc_args\": [\"string\"],
            \"sound\": \"string\",
            \"title_loc_key\": \"string\",
            \"title\": \"string\",
            \"body\": \"string\",
            \"click_action\": \"clicky_clacky\",
            \"body_loc_key\": \"string\"
          },
          \"data\": {
            \"dataAndroid\": \"priority message\"
          },
          \"ttl\": \"10023.32s\"
        },
        \"apns\": {
          \"payload\": {
            \"aps\": {
              \"alert\": {
                \"subtitle\": \"string\",
                \"title-loc-args\": [\"string\"],
                \"title-loc-key\": \"string\",
                \"loc-args\": [\"string\"],
                \"loc-key\": \"string\",
                \"title\": \"string\",
                \"body\": \"string\"
              },
              \"category\": \"Click\",
              \"content-available\": 0,
              \"sound\": \"string\",
              \"badge\": 5
            }
          }
        },
        \"webpush\": {
          \"notification\": {
            \"badge\": \"5\",
            \"title\": \"string\",
            \"body\": \"string\"
          },
          \"data\": {
            \"dataWeb\": \"priority message\"
          }
        }
      }
    }
  }"
}
```

发送 JSON 有效载荷时，请务必在请求中包含该 `message-structure` 属性，并将其设置为 `json`。

**CLI 示例：**

```
aws sns publish --topic $TOPIC_ARN --message '{"GCM": "{\"fcmV1Message\": {\"message\":{\"notification\":{\"title\":\"string\",\"body\":\"string\"},\"android\":{\"priority\":\"high\",\"notification\":{\"title\":\"string\",\"body\":\"string\"},\"data\":{\"customAndroidDataKey\":\"custom key value\"},\"ttl\":\"0s\"},\"apns\":{\"payload\":{\"aps\":{\"alert\":{\"title\":\"string\", \"body\":\"string\"},\"content-available\":1,\"badge\":5}}},\"webpush\":{\"notification\":{\"badge\":\"URL\",\"body\":\"Test\"},\"data\":{\"customWebpushDataKey\":\"priority message\"}},\"data\":{\"customGeneralDataKey\":\"priority message\"}}}}", "default": "{\"notification\": {\"title\": \"test\"}"}' --region $REGION --message-structure json
```

*有关发送 FCM v1 格式的有效载荷的更多信息，请参阅 Google 的 Firebase* 文档中的以下内容：
+ [从旧版 FCM 迁移 APIs 到 HTTP v1](https://firebase.google.com/docs/cloud-messaging/migrate-v1)
+ [关于 FCM 消息](https://firebase.google.com/docs/cloud-messaging/concept-options#customizing_a_message_across_platforms)
+ [REST 资源：projects.messages](https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages)

## 使用旧版有效载荷结构向 FCM v1 API 发送消息
<a name="sns-fcm-v1-legacy-payload-structure"></a>

迁移到 FCM v1 时，您无需更改用于旧版凭证的有效载荷结构。Amazon SNS 会将您的有效载荷转换为新的 FCM v1 有效载荷结构，然后发送给 Google。

输入消息有效载荷格式：

```
{
  "GCM": "{\"notification\": {\"title\": \"string\", \"body\": \"string\", \"android_channel_id\": \"string\", \"body_loc_args\": [\"string\"], \"body_loc_key\": \"string\", \"click_action\": \"string\", \"color\": \"string\", \"icon\": \"string\", \"sound\": \"string\", \"tag\": \"string\", \"title_loc_args\": [\"string\"], \"title_loc_key\": \"string\"}, \"data\": {\"message\": \"priority message\"}}"
}
```

发送给 Google 的消息：

```
{
  "message": {
    "token": "***",
    "notification": {
      "title": "string",
      "body": "string"
    },
    "android": {
      "priority": "high",
      "notification": {
        "body_loc_args": [
          "string"
        ],
        "title_loc_args": [
          "string"
        ],
        "color": "string",
        "sound": "string",
        "icon": "string",
        "tag": "string",
        "title_loc_key": "string",
        "title": "string",
        "body": "string",
        "click_action": "string",
        "channel_id": "string",
        "body_loc_key": "string"
      },
      "data": {
        "message": "priority message"
      }
    },
    "apns": {
      "payload": {
        "aps": {
          "alert": {
            "title-loc-args": [
              "string"
            ],
            "title-loc-key": "string",
            "loc-args": [
              "string"
            ],
            "loc-key": "string",
            "title": "string",
            "body": "string"
          },
          "category": "string",
          "sound": "string"
        }
      }
    },
    "webpush": {
      "notification": {
        "icon": "string",
        "tag": "string",
        "body": "string",
        "title": "string"
      },
      "data": {
        "message": "priority message"
      }
    },
    "data": {
      "message": "priority message"
    }
  }
}
```

**潜在风险**
+ 旧版到 v1 的映射不支持 Apple 推送通知服务（APNS）`headers` 或 `fcm_options` 键。如果希望使用这些字段，请发送 FCM v1 有效载荷。
+ 在某些情况下，FCM v1 要求消息标头才能向您的 APNs 设备发送静默通知。如果您当前正在向 APNs 设备发送静默通知，则它们不适用于传统方法。相反，我们建议使用 FCM v1 有效载荷以避免意外问题。要查找 APNs 标题列表及其用途，请参阅《*Apple 开发者指南》 APNs*中的 “[与之通信](https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/CommunicatingwithAPNs.html)”。
+ 如果您在发送通知时使用的是 `TTL` Amazon SNS 属性，则它只会在 `android` 字段中进行更新。如果您想设置 `TTL` APNS 属性，请使用 FCM v1 有效载荷。
+ `android`、`apns` 和 `webpush` 键将被映射并用所提供的所有相关键填充。例如，如果您提供 `title`（这是所有三个平台之间共享的键），FCM v1 映射将使用您提供的标题填充所有三个平台。
+ 一些平台间的共享键需要不同的值类型。例如，传递给 `apns` 的 `badge` 键需要一个整数值，而传递给 `webpush` 的 `badge` 键需要一个字符串值。如果您提供了 `badge` 键，FCM v1 映射将仅填充您为其提供了有效值的键。

## FCM 传输失败事件
<a name="sns-fcm-delivery-failure-events"></a>

下表提供了 Amazon SNS 失败类型，该类型与从 Google 收到的 FCM v1 通知请求的错误/状态代码相对应。当您为应用程序设置[交付状态日志 CloudWatch ](topics-attrib.md)时，可以查看从 FCM v1 API 收到的所有观察到的错误代码。


| FCM 代码 error/status  | Amazon SNS 失败类型 | 失败消息 | 原因和缓解措施 | 
| --- | --- | --- | --- | 
|  `UNREGISTERED`  |  `InvalidPlatformToken`  |  与端点关联的平台令牌无效。  |  连接到您的端点的设备令牌已过时或无效。Amazon SNS 禁用了您的端点。将 Amazon SNS 端点更新为最新的设备令牌。  | 
|  `INVALID_ARGUMENT`  |  `InvalidNotification`  |  通知正文无效。  |  设备令牌或消息有效载荷可能无效。验证您的消息有效载荷是否有效。如果消息有效载荷有效，请将 Amazon SNS 端点更新为最新的设备令牌。  | 
|  `SENDER_ID_MISMATCH`  |  `InvalidPlatformToken`  |  与端点关联的平台令牌无效。  |  与设备令牌关联的平台应用程序无权向设备令牌发送消息。确认您在 Amazon SNS 平台应用程序中使用了正确的 FCM 凭证。  | 
|  `UNAVAILABLE`  |  `DependencyUnavailable`  |  依赖关系不可用。  |  FCM 无法实时处理请求。Amazon SNS 执行的所有重试都失败。您可以将这些消息存储在死信队列（DLQ）中，以后再重新发送它们。  | 
|  `INTERNAL`  |  `UnexpectedFailure`  |  意外失败；请联系 Amazon。失败短语 [内部错误]。  |  FCM 服务器在处理您的请求时遇到错误。Amazon SNS 执行的所有重试都失败。您可以将这些消息存储在死信队列（DLQ）中，以后再重新发送它们。  | 
|  `THIRD_PARTY_AUTH_ERROR`  |  `InvalidCredentials`  |  平台应用程序凭证无效。  |  无法发送针对 iOS 设备或 Webpush 设备的消息。验证您的开发和生产凭证是否有效。  | 
|  `QUOTA_EXCEEDED`  |  `Throttled`  |  请求受 [gcm] 限制。  |  已超过消息速率配额、设备消息速率配额或主题消息速率配额。有关如何解决此问题的信息，请参阅 [ErrorCode](https://firebase.google.com/docs/reference/fcm/rest/v1/ErrorCode)Google 的 *Firebase* 文档中的。  | 
|  `PERMISSION_DENIED`  |  `InvalidNotification`  |  通知正文无效。  |  如果出现 `PERMISSION_DENIED` 异常，则调用方（您的 FCM 应用程序）无权在有效载荷中执行指定操作。导航到您的 FCM 控制台，并验证您的凭证是否启用了所需的 API 操作。  | 