尝试通过Firebase Cloud Messaging(FCM)向所有用户发送推送通知


image.png

这次,我想实现一个使用FirebaseCloudMessaging的Topic消息功能通过CloudFunctions向所有用户发送Push通知的实现。

你怎么做呢?

FCM主题消息传递
我们将使用函数来实现它。步骤如下。

  • 在客户端上注册主题

    • 这次我将向Swift(客户端)注册Topic,但是我将使用FirebaseAdmin SDK来注册客户端
      还有一种使用获得的fcm_token进行注册的方法,因此,请参见此处以获取详细信息。
  • 创建发送消息的功能

    • 创建一个HTTP函数以将全局推送发送到FirebaseCloudFunctions。

      • 请参阅有关FirebaseCloudFunctions引入的以前的文章。
  • 发送消息

  • 开始工作??????

    1.在客户端上注册主题

    首先,订阅Topic,以便可以在Swift中收到有关Topic的通知。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
            // 省略.....
            initFirebaseMessaging()
            // 省略.....
            return true
        }

        private func subscribeGeneralMessaging() {
            Messaging.messaging().subscribe(toTopic: "general")
        }

        private func initFirebaseMessaging() {
            Messaging.messaging().delegate = self
            InstanceID.instanceID().instanceID {[weak self](result, error) in
                if let result = result {
                    self?.subscribeGeneralMessaging()
                    // 省略.....
                }
            }
        }

        // MARK: - MessagingDelegate
        func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String) {
            subscribeGeneralMessaging()
            // 省略.....
        }

    订阅过程也已添加到MessagingDelegate的didReceiveRegistrationToken中,以便即使在中间允许应用程序推送通知时也可以使用它。

    2.创建一个发送消息的功能

    现在,客户端已准备好接收主题通知,我想创建一个CloudFunctions HTTP函数来发送主题消息。这次我将省略上一篇文章中提到的介绍方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    exports.push_to_general = functions.https.onRequest((request, response) => {
      try {
        const idToken = getIdToken(request, response);
        admin.auth().verifyIdToken(idToken)
          .then(function(decodedToken){
            if ((request.body.title !== undefined) && (request.body.body !== undefined)) {
              const topic = 'general';
              const message = {
                notification: {
                  title: request.body.title,
                  body: request.body.body
                },
                topic: topic
              };
              admin.messaging().send(message)
                .then(pushResponse => {
                  console.log("Successfully send message:", pushResponse);
                  response.status(200).send({ message: 'Successfully send message' });
                })
                .catch(error => {
                  console.log("Error sending message:", error);
                  response.status(400).send({ message: 'Error sending message' });
                });
            } else {
              response.status(400).send({ message: 'Invalid request method' });
            };
          });
      } catch (error) {
        console.log(error.message);
        response.status(401).send({ message: error.message })
      };
    });

    function getIdToken(request, response) {
      if (!request.headers.authorization) {
        throw new Error('Not found authentication header')
      }
      const match = request.headers.authorization.match(/^Bearer (.*)$/)
      if (match) {
        const idToken = match[1]
        return idToken
      }
      throw new Error(
        'Unable to get authentication header',
      )
    }

    对于

    功能的身份验证,使用用户的访问令牌执行授权。另外,虽然与本次内容有所不同,但是如果您已注册两个主题之一,则可以添加如下条件,例如发送通知,因此请参阅正式文档,请尝试。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // Define a condition which will send to devices which are subscribed
    // to either the Google stock or the tech industry topics.
    var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

    // See documentation on defining a message payload.
    var message = {
      notification: {
        title: '$GOOG up 1.43% on the day',
        body: '$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.'
      },
      condition: condition
    };

    // Send a message to devices subscribed to the combination of topics
    // specified by the provided condition.
    admin.messaging().send(message)
      .then((response) => {
        // Response is a message ID string.
        console.log('Successfully sent message:', response);
      })
      .catch((error) => {
        console.log('Error sending message:', error);
      });

    3.发送消息

    现在您已经准备好发送主题消息,让我们使用curl运行该函数。

    1
    curl -X POST -H "Authorization: Bearer your_id_token" https://hogehoge.cloudfunctions.net/push_to_general -d "title=iOSエンジニアのつぶやき&body=渓流釣りしたいなあ"

    您是否成功收到如下主题信息?

    image.png

    参考

    • https://firebase.google.com/docs/cloud-messaging/ios/topic-messaging?hl=ja