使用 React Native、Expo 和 AWS Amplify 实现推送通知的指南总结

2025-06-11

使用 React Native、Expo 和 AWS Amplify 实现推送通知的指南

结论

如果您开发一款应用,您希望能够吸引客户,让他们尽可能多地使用您的应用,并让应用为他们带来价值。因此,您必须设置推送通知。在本指南中,我将向您展示如何使用一些优秀的工具来实现这一点。我们将构建一个简单的应用来演示推送通知。

有一些强大的工具可以使应用程序开发尽可能简单。

反应原生

React Native 很棒,因为你只需用 JavaScript 编写代码,然后编译到 iOS 和 Android 系统即可。因此成本更低,开发周期更快。

世博会

Expo 之所以表现良好,是因为它包含了许多您需要的功能,并且您无需安装任何其他工具甚至无需 Mac 即可为 IOS 和 Android 进行开发。

AWS Amplify

AWS Amplify 是这些工具与后端之间的粘合剂。在这里,您还可以使用 Javascript 设置 API、存储、身份验证和授权、数据库、数据存储等。

推送通知

当你深入研究这些工具集并设置好你的架构后,你就会开始爱上它们。而当你需要使用推送通知时,你就不得不告别 Expo 了,因为 AWS Amplify 并没有提供开箱即用的解决方案,让你无需弹出即可使用推送通知。幸运的是,AWS 有更多支持无需弹出即可使用推送通知的工具。

建筑学

我们将使用 AWS Amplify、AWS Pinpoint、AWS Lambda、AWS DynamoDB 和 Expo Push Notifications Server 来完成它。

替代文本

在此示例中,我们将在应用中发送一条消息。我们将通过AWS Lambda Pinpoint创建一个定时 Pinpoint 活动(这也可以是一个即时活动)。一旦活动触发,首先会启动一个钩子。此钩子会将活动数据发送到AWS Lambda 推送通知。我们将准备推送通知消息,并通过 Expo Server SDK 将其发送到 Expo。这会将推送消息发送到客户端,也就是您的应用。同时,活动数据已发送回 AWS Pinpoint,以便进一步发送到其他渠道(如果您需要)。您将设置一个电子邮件渠道,以便了解其工作原理。

入门

我将使用 NPM,但当然您也可以使用 Yarn。

设置 React Native

首先,我们将创建要使用的 React Native 应用程序。

$ npx expo init pushApp

> Choose a template: blank

$ cd pushApp

$ npm install aws-amplify aws-amplify-react-native

设置 AWS Amplify

首先,我们需要安装 AWS Amplify CLI。Amplify CLI 是一个命令行工具,可用于创建和部署各种 AWS 服务。

要安装 CLI,我们将运行以下命令:

$ npm install -g @aws-amplify/cli

接下来,我们将使用来自 AWS 账户的用户配置 CLI:

$ amplify configure

要观看 CLI 配置过程的视频演示,请单击

现在我们可以从 React Native 应用程序的根目录中初始化一个新的 Amplify 项目:

$ amplify init

这里我们将指导您完成一系列步骤:

  • 输入项目名称:  amplifypushapp  (或您喜欢的项目名称)
  • 输入环境名称:  dev  (使用此名称,因为我们将引用它)
  • 选择您的默认编辑器:  Visual Studio Code  (或您的文本编辑器)
  • 选择您正在构建的应用程序类型:  javascript
  • 您正在使用什么 JavaScript 框架:  react-native
  • 源目录路径:  /
  • 分发目录路径:  build
  • 构建命令:  npm run-script build
  • 启动命令:  npm run-script start
  • 您想使用 AWS 配置文件吗? 
  • 请选择您要使用的配置文件:  YOUR_USER_PROFILE
  • 现在,我们的 Amplify 项目已经创建,我们可以继续下一步。

将 Graphql 添加到你的项目中

您的 React Native 应用已启动并运行,AWS Amplify 也已配置完毕。Amplify 提供多种服务,您可以使用它们来丰富您的应用。我们主要关注 API 服务。所以,让我们添加一个 API。

Amplify add api

以下步骤将会发生:

  • 选择Graphql
  • 输入 API 的名称:pushAPI(您喜欢的 API 名称)
  • 为 API 选择授权类型:Amazon Cognito 用户池(因为我们仅对经过身份验证的用户使用此应用程序,但您可以选择其他选项)
  • 选择是否使用默认身份验证和安全配置:默认配置
  • 您希望用户如何登录?用户名(同时启用 AWS Amplify Auth 模块)
  • 您要配置高级设置吗?不,我已经完成了。
  • 您有带注释的 GraphQL 架构吗
  • 您想要引导模式创建吗?:n
  • 提供自定义类型名称:用户

您的 API 和架构定义现已创建。您可以在项目目录中找到它:

Amplify > backend > api > name of your api

@model 指令将为您创建一个 DynamoDB。还有更多可能的指令,如需完整说明,请参阅AWS Amplify 文档

配置 AWS 电子邮件服务

登录控制台并访问 SES 服务。然后按照以下说明配置并激活电子邮件地址。您稍后需要使用此电子邮件地址作为发送邮件的地址。

https://docs.aws.amazon.com/ses/latest/DeveloperGuide/setting-up-email.html

向您的项目添加分析

我们将在您的项目中添加分析功能,因为目前这是从您的 pinpoint 函数设置对 pinpoint 的访问权限的最简单方法。您也可以修改 CloudFormation 模板来实现此目的。

Amplify add analytics

使用您的信息完成这些步骤。

向您的项目添加函数

通过添加函数,我们将创建 Lambda。

Amplify add function

请按照以下步骤操作:

  • 为您的资源提供一个友好名称,以用作项目中此类别的标签:pushNotification
  • 提供 AWS Lambda 函数名称:
  • 选择要使用的函数模板:Hello world 函数
  • 您想从 Lambda 函数访问此项目中创建的其他资源吗?
  • 选择类别api
  • 选择您想要允许 pushAPI读取的操作
  • 您要立即编辑本地 lambda 函数吗?N

再次重复此步骤,但调用下一个函数精确定位并使用以下信息回答以下步骤:

  • 您想从 Lambda 函数访问此项目中创建的其他资源吗?
  • 选择类别分析
  • 选择要允许 Analytics创建、读取、更新、删除的操作
  • 您要立即编辑本地 lambda 函数吗?N

您的函数现已创建,您可以在项目目录中找到它:

Amplify > backend > function > name of your function

进入Pinpoint 函数的src 目录并安装此包


$ npm install aws-sdk

打开 index.js 文件并粘贴此代码。请仔细检查代码并替换正确的值。

/* Amplify Params - DO NOT EDIT
You can access the following resource attributes as environment variables from your Lambda function
var environment = process.env.ENV
var region = process.env.REGION
var apiPushAPIGraphQLAPIIdOutput = process.env.API_PUSHAPI_GRAPHQLAPIIDOUTPUT
var apiPushAPIGraphQLAPIEndpointOutput = process.env.API_PUSHAPI_GRAPHQLAPIENDPOINTOUTPUT
var analyticsAmplifypushappId = process.env.ANALYTICS_AMPLIFYPUSHAPP_ID
var analyticsAmplifypushappRegion = process.env.ANALYTICS_AMPLIFYPUSHAPP_REGION

Amplify Params - DO NOT EDIT */

const AWS = require("aws-sdk");
AWS.config.region = "<REGION>"; // fill in your right region ******
const pinpoint = new AWS.Pinpoint();

exports.handler = async (event, context) => {
  try {
    event = event.arguments.input;

    // Create a AWS Pinpoint project
    const appID = await createApp();

    // Enable the SES email address for the project
    enableChannels(appID, event.email);

    // Create the endpoints for the Pinpoint project/app
    await createEndPoints(
      appID,
      event.id,
      event.email,
      event.name,
      event.token
    );

    // Create a segment where you want to filter the endpoint you want to send a message to
    const segmentID = await createSegment(appID);

    // create starter segment and campaign.
    const hookLambda = "pushNotification-dev";
    const result = await createCampaign(
      appID,
      event.message,
      hookLambda,
      segmentID
    );

    return result;
  } catch (error) {
    console.log("Oops! An error happened.");
  }
};

async function createApp() {
  let params = {
    CreateApplicationRequest: {
      /* required */
      Name: "Push App" /* Campaign name, required */
    }
  };

  return new Promise((res, rej) => {
    pinpoint.createApp(params, function(err, data) {
      if (err) {
        rej(err);
        console.log(err, err.stack); // an error occurred
      } else {
        res(data.ApplicationResponse.Id); //console.log(data);// successful response
      }
    });
  });
}

/*
When you create a new pinpoint app you need to activate an emailaddress where the emails can be send from
*/
function enableChannels(appID, email) {
  console.log(appID, email);
  var params = {
    ApplicationId: appID /* required */,
    EmailChannelRequest: {
      /* required */
      FromAddress:
        "<FROM EMAIL ADDRESS>" /* use the emailaddress that you activated in AWS SES, required  */,
      Identity:
        "arn:aws:ses:<REGION>:<ACCOUNTID>:identity/" + email /* required */,
      Enabled: true
    }
  };
  pinpoint.updateEmailChannel(params, function(err, data) {
    if (err) console.log(err, err.stack);
    else console.log(data); // successful response
  });
}

/*
An endpoint is an object which contains user data which you can use later in a segment to send messages
*/
async function createEndPoints(appID, id, email, name, token) {

  let params = {
    ApplicationId: appID /* required */,
    EndpointId: id /* required */,
    EndpointRequest: {
      /* required */
      Address: email,
      ChannelType: "EMAIL",
      EndpointStatus: "ACTIVE",
      OptOut: "NONE",
      User: {
        UserAttributes: {
          name: [
            name
            /* more items */
          ],
          expoToken: [
            token
            /* more items */
          ]
        }
      }
    }
  };

  await pinpoint.updateEndpoint(params, function(err, data) {
    if (err) {
      console.log(err, err.stack);
      // an error occurred
    } else {
      console.log(data); // successful response
    }
  });
}

function createSegment(appID) {
  let params = {
    ApplicationId: appID /* required */,
    WriteSegmentRequest: {
      /* required */
      Dimensions: {
        Demographic: {
          Channel: {
            Values: [
              /* required */
              "EMAIL"
              /* more items */
            ],
            DimensionType: "INCLUSIVE"
          }
        }
      },
      Name: "Segment"
    }
  };

  return new Promise((res, rej) => {
    pinpoint.createSegment(params, function(err, data) {
      if (err) {
        rej(err);
        console.log(err, err.stack); // an error occurred
      } else {
        res(data.SegmentResponse.Id); //console.log(data);// successful response
      }
    });
  });
}
/*
With the endpoint(s) created you can create a segment. A segment is a filter which selects the right endpionts to send messages to
*/
async function createCampaign(appID, message, env, segmentID) {
  const utcDate = new Date(Date.now());

  const params = {
    ApplicationId: appID /* required */,
    WriteCampaignRequest: {
      /* required */
      HoldoutPercent: 0,
      Hook: {
        LambdaFunctionName: env,
        Mode: "FILTER"
      },
      IsPaused: false,
      Limits: {},
      MessageConfiguration: {
        EmailMessage: {
          Title: "Test Email Message",
          HtmlBody:
            `<!DOCTYPE html>\n    <html lang="en">\n    <head>\n    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />\n</head>\n<body>\n<H2>Hallo {{User.UserAttributes.name}},</H2>\n\n <br />This is a Text Message from PinPoint. \n You have send this text: \n\n` +
            message +
            `\n</body>\n</html>`,
          FromAddress: "<FROM EMAIL ADDRESS>"
        },
        DefaultMessage: {
          // you push message
          Body: message
        }
      },
      Name: "push campaign",
      Schedule: {
        IsLocalTime: false,
        QuietTime: {},
        StartTime: utcDate.toISOString(),
        Frequency: "ONCE"
      },
      SegmentId: String(segmentID),
      SegmentVersion: 1,
      tags: {}
    }
  };

  return new Promise((res, rej) => {
    pinpoint.createCampaign(params, function(err, data) {
      if (err) {
        console.log(err, err.stack); // an error occurred
        const response = {
          statusCode: 500,
          body: JSON.stringify(err)
        };
        rej(response);
      } else {
        console.log(data);
        const response = {
          statusCode: 200,
          body: JSON.stringify(data)
        };

        res(response); // successful response
      }
    });
  });
}


快完成了。现在让我们实现下一个函数。转到 Push Notifications 目录,然后转到src目录。安装此 NPM 包


$ npm install expo-server-sdk

打开 index.js 并粘贴此代码

/* Amplify Params - DO NOT EDIT
You can access the following resource attributes as environment variables from your Lambda function
var environment = process.env.ENV
var region = process.env.REGION
var apiPushAPIGraphQLAPIIdOutput = process.env.API_PUSHAPI_GRAPHQLAPIIDOUTPUT
var apiPushAPIGraphQLAPIEndpointOutput = process.env.API_PUSHAPI_GRAPHQLAPIENDPOINTOUTPUT

Amplify Params - DO NOT EDIT */ const {
  Expo
} = require("expo-server-sdk");

// Create a new Expo SDK client
let expo = new Expo();

exports.handler = function(event, context, callback) {
  try {
    let messages = [];

    // prettier-ignore
    for (var key in event.Endpoints) {
    if (event.Endpoints.hasOwnProperty(key)) {
      var endpoint = event.Endpoints[key];

        messages.push({
          to: String(endpoint.User.UserAttributes.expoToken),
          sound: "default",
          body: event.Message.apnsmessage.body,
           data: { "status": "ok" }
        });

    }
  }

    // The Expo push notification service accepts batches of notifications so
    // that you don't need to send 1000 requests to send 1000 notifications. We
    // recommend you batch your notifications to reduce the number of requests
    // and to compress them (notifications with similar content will get
    // compressed).
    let chunks = expo.chunkPushNotifications(messages);
    let tickets = [];
    (async () => {
      // Send the chunks to the Expo push notification service. There are
      // different strategies you could use. A simple one is to send one chunk at a
      // time, which nicely spreads the load out over time:
      for (let chunk of chunks) {
        try {
          let ticketChunk = await expo.sendPushNotificationsAsync(chunk);
          console.log(ticketChunk);
          tickets.push(...ticketChunk);
          // NOTE: If a ticket contains an error code in ticket.details.error, you
          // must handle it appropriately. The error codes are listed in the Expo
          // documentation:
          // https://docs.expo.io/versions/latest/guides/push-notifications#response-format
        } catch (error) {
          console.error(error);
        }
      }
    })();

    // Later, after the Expo push notification service has delivered the
    // notifications to Apple or Google (usually quickly, but allow the the service
    // up to 30 minutes when under load), a "receipt" for each notification is
    // created. The receipts will be available for at least a day; stale receipts
    // are deleted.
    //
    // The ID of each receipt is sent back in the response "ticket" for each
    // notification. In summary, sending a notification produces a ticket, which
    // contains a receipt ID you later use to get the receipt.
    //
    // The receipts may contain error codes to which you must respond. In
    // particular, Apple or Google may block apps that continue to send
    // notifications to devices that have blocked notifications or have uninstalled
    // your app. Expo does not control this policy and sends back the feedback from
    // Apple and Google so you can handle it appropriately.
    let receiptIds = [];
    for (let ticket of tickets) {
      // NOTE: Not all tickets have IDs; for example, tickets for notifications
      // that could not be enqueued will have error information and no receipt ID.
      if (ticket.id) {
        receiptIds.push(ticket.id);
      }
    }

    let receiptIdChunks = expo.chunkPushNotificationReceiptIds(receiptIds);
    async () => {
      // Like sending notifications, there are different strategies you could use
      // to retrieve batches of receipts from the Expo service.
      for (let chunk of receiptIdChunks) {
        try {
          let receipts = await expo.getPushNotificationReceiptsAsync(chunk);
          console.log(receipts);

          // The receipts specify whether Apple or Google successfully received the
          // notification and information about an error, if one occurred.
          for (let receipt of receipts) {
            if (receipt.status === "ok") {
              continue;
            } else if (receipt.status === "error") {
              console.error(
                `There was an error sending a notification: ${receipt.message}`
              );
              if (receipt.details && receipt.details.error) {
                // The error codes are listed in the Expo documentation:
                // https://docs.expo.io/versions/latest/guides/push-notifications#response-format
                // You must handle the errors appropriately.
                console.error(`The error code is ${receipt.details.error}`);
              }
            }
          }
        } catch (error) {
          console.error(error);
        }
      }
    };

    callback(null, event.Endpoints);
  } catch (error) {
    callback(error);
  }
};

现在我们需要先将所有服务推送到云端。转到项目根目录并运行以下命令

amplify push

请按照以下步骤操作:

  • 您是否要为新创建的 GraphQL API 生成代码?是的
  • 选择代码生成语言目标Javascript
  • 输入 graphql 查询、突变和订阅的文件名模式Enter(默认)
  • 您是否想要生成/更新所有可能的 GraphQL 操作(查询、变更和订阅)?
  • 输入最大语句深度 [如果架构嵌套较深,则从默认值增加]输入(默认值)

返回pushNotification 函数的src目录。打开此文件:pushNotification-cloudformation-template.json,然后转到“Resources”部分并粘贴以下代码:

    "LambdaInvokePermission": {
            "Type": "AWS::Lambda::Permission",
            "Properties": {
                "Action": "lambda:InvokeFunction",
                "FunctionName": {
                    "Fn::If": [
                        "ShouldNotCreateEnvResources",
                        "pushNotification",
                        {
                            "Fn::Join": [
                                "",
                                [
                                    "pushNotification",
                                    "-",
                                    {
                                        "Ref": "env"
                                    }
                                ]
                            ]
                        }
                    ]
                },
                "Principal": {
                    "Fn::Sub": [
                        "pinpoint.${region}.amazonaws.com",
                        {
                            "region": {
                                "Ref": "AWS::Region"
                            }
                        }
                    ]
                },
                "SourceArn": {
                    "Fn::Sub": [
                        "arn:aws:mobiletargeting:${region}:${account}:/apps/*",
                        {
                            "region": {
                                "Ref": "AWS::Region"
                            },
                            "account": {
                                "Ref": "AWS::AccountId"
                            }
                        }
                    ]
                }
            }
        },

保存文件。此代码将设置权限,以便 AWS Pinpoint 可以作为钩子调用 Lambda。您必须单独进行推送。如果您尝试与之前的推送同时进行,则在尝试设置权限时,可能会出现并非所有服务都已推送的情况。

amplify push

前往:

Amplify > backend > api > name of your api > open schema.graphql

现在函数已经部署完毕,我们还需要更新架构。将此代码放入 schema.graphql 文件中。它会创建一个额外的变更,以便你在应用中调用这些函数。

type User @model {
  id: ID!
  name: String!
  email: String!
  expoToken: String
}

type Mutation {
  pinpoint(input: pinpointInput): pinpointResult
    @function(name: "pinpoint-${env}")
}

type pinpointResult {
  statusCode: Int
  body: String
}

input pinpointInput {
  token: String!
  name: String!
  email: String!
  message: String!
  id: String!
}

再推一下

amplify push
  • 您确定要继续吗?Y

转到项目的根目录,然后到 src 目录 > graphql > mutations.js 检查此代码是否存在,如果没有,请添加并保存:

export const pinpoint = /* GraphQL */ `
  mutation pinpoint($input: pinpointInput!) {
    pinpoint(input: $input) {
      statusCode
      body
    }
  }
`;

通过 Cognito 和 AppSync 添加一些数据

进入AWS Cognito控制台,点击“管理用户池”,然后点击“用户池”>“用户和组”>“创建用户”。填写表单,并将所有复选框保留为已选中状态。点击新用户并记下子值例如 b14cc22-c73f-4775-afd7-b54f222q4758),然后转到菜单中的“应用程序客户端”,记下来自客户端 Web(底部)的应用程序客户端 ID,并在下一步中使用这些值。

让我们添加一些您可以在应用中使用的数据。前往控制台中的 AppSync 服务。

  • 通过控制台转到AWS AppSync 。
  • 打开你的项目
  • 点击查询
  • 通过单击“通过 Cognito 用户池登录”按钮,使用 Cognito 用户登录(您可以在控制台中或通过您的应用程序通过 Cognito 创建用户)(使用您写下的数据)
  • 添加以下代码并运行代码(使用您的电子邮件地址更新):
mutation PutUser {
  createUser( input: {
    id: "b14cc22-c73f-4775-afd7-b54f222q4758",
    name: "Ramon", 
    email: "<EMAILADDRESS>"
  }
  ){
    id
    name
    email
  }
}

让我们构建 React Native 应用

我做了一个简单(略显丑陋,所有功能都由两个组件组成)的应用。用户需要登录后,我们会获取他的用户资料,检查是否有有效的 ExpoToken,如果没有,我们会请求一个并将其保存在资料中。在应用中,用户可以发送消息,该消息会通过推送通知和电子邮件发送给用户。

转到项目根目录并打开 App.js 并将其替换为以下代码:

import React from "react";
import { withAuthenticator } from "aws-amplify-react-native";
import Amplify, { Analytics } from "aws-amplify";

// Get the aws resources configuration parameters
import awsconfig from "./aws-exports"; // if you are using Amplify CLI
import Main from "./src/Main";

Amplify.configure(awsconfig);
Analytics.disable(); // disabled analytics otherwise you get annoying messages

class App extends React.Component {
  render() {
    return <Main />;
  }
}

export default withAuthenticator(App);

这将导入你需要的所有内容,并使用 HOC withAuthenticator 包装你的应用。这将为你的应用创建登录和注册功能。

现在在src 文件夹中创建一个名为Main.js 的文件并粘贴以下代码:

import React from "react";
import { View, TextInput, Button } from "react-native";
import * as queries from "./graphql/queries.js";
import * as mutations from "./graphql/mutations";
import { API, graphqlOperation, Auth } from "aws-amplify";
import { Notifications } from "expo";
import * as Permissions from "expo-permissions";

class Main extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      profile: {},
      message: "",
      user: ""
    };
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  async componentDidMount() {
    const user = await Auth.currentSession()
      .then(data => {
        this.setState({ user: data.idToken.payload.sub });
        return data.idToken.payload.sub;
      })
      .catch(err => console.log(err));

    const profile = await this.getUserProfile(user);

    // There is no expoToken available yet, so we will request that and save it into the profile
    if (profile.expoToken === null) {
      const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);

      if (status !== "granted") {
        alert("No notification permissions!");
        return;
      }

      let token = await Notifications.getExpoPushTokenAsync();

      // Only update the profile with the expoToken if it not exists yet
      if (token !== "") {
        const inputParams = {
          id: user,
          expoToken: token
        };
        await API.graphql(
          graphqlOperation(mutations.updateUser, { input: inputParams })
        )
          .then(result => {
            console.log(result);
          })
          .catch(err => console.log(err));
      }
    }
  }

  async getUserProfile(sub) {
    const result = await API.graphql(
      graphqlOperation(queries.getUser, { id: sub })
    )
      .then(result => {
        this.setState({
          profile: result.data.getUser
        });
        return result.data.getUser;
      })
      .catch(err => console.log(err));

    return result;
  }

  async handleSubmit() {
    const inputParams = {
      message: this.state.message,
      token: this.state.profile.expoToken,
      name: this.state.profile.name,
      email: this.state.profile.email,
      id: this.state.user
    };

    await API.graphql(
      graphqlOperation(mutations.pinpoint, { input: inputParams })
    )
      .then(result => {
        console.log(result);
        console.log("success");
        this.setState({ message: "" });
      })
      .catch(err => console.log(err));
  }

  render() {
    return (
      <View style={{ marginTop: 80, marginLeft: 10, marginRight: 10 }}>
        <TextInput
          placeholder="Your push message"
          value={this.state.message}
          onChangeText={input => this.setState({ message: input })}
          style={{
            paddingLeft: 5,
            height: 40,
            fontSize: 16,
            marginBottom: 6,
            marginTop: 2
          }}
        ></TextInput>
        <Button title="Submit" onPress={this.handleSubmit} />
      </View>
    );
  }
}

export default Main;

您的应用程序已准备就绪,您可以从根项目启动它:

expo start"

您需要在实体设备上安装 Expo 客户端并启动应用,否则无法测试推送通知。使用您通过 AWS Cognito 创建的用户登录,填写推送消息,等待几秒钟……然后……您就会在应用中收到推送消息,并在您的帐户中收到一封电子邮件。

替代文本

结论

你能用这些优秀的工具(AWS Amplify、React Native 和 Expo)快速将这些功能交付给客户,真是太棒了。你的应用已经准备好吸引客户了 :)

我一直在努力让推送通知正常运行,同时又要保留所有工具,以便能够从中受益。我必须突破当前的限制,于是就想出了这个架构和实现方案。

希望你喜欢这篇指南,也期待你在评论区留言反馈,或者分享你已实现此设置的项目。祝你编程愉快!

实际代码请见 github:[ https://github.com/rpostulart/pushapp ]

参考链接:https://dev.to/aws-builders/the-guide-to-implement-push-notifications-with-react-native-expo-and-aws-amplify-4imn
PREV
Next.js 的三个新功能及其使用方法
NEXT
节省 AWS Lambda Amazon CloudWatch Logs 成本