#push #fcm #firebase #messaging #messages #listener #cloud

fcm-push-listener

监听来自 Firebase Cloud Messaging (FCM) 的推送消息

10 个版本 (6 个稳定版)

3.0.0 2024 年 1 月 13 日
2.0.3 2023 年 12 月 23 日
2.0.2 2023 年 11 月 23 日
2.0.1 2023 年 3 月 12 日
0.1.1 2023 年 2 月 26 日

#653网页开发

每月 下载 38

MIT 许可证

36KB
607

概述

此 crate 将监听来自 Firebase Cloud Messaging (FCM) 的推送消息。

重要

对于 3.0.0 版本之前的版本,注册将在 2024 年 6 月 20 日停止工作,因为 Google 将关闭一个它所调用的 API。您需要在此时间之前升级,以便库继续工作。

先决条件

  1. Firebase App ID - Firebase 控制台 -> 项目设置 -> 通用 -> 您的应用 -> App ID

将其制作为一个 Android 应用,因为我们将会调用 Android 设备检查 API。

  1. Firebase 项目 ID - Firebase 控制台 -> 项目设置 -> 通用 -> 项目 ID
  2. Firebase API 密钥 - Google Cloud 控制台 -> API 和服务 -> 凭据 -> API 密钥

API 密钥所需的权限:Firebase Cloud Messaging API、云消息、Firebase 安装 API、FCM 注册 API。

  1. VAPID 密钥 - Firebase 控制台 -> 项目设置 -> 云消息 -> 网页配置 -> 网页推送证书

您需要的是“密钥对”列下列出的公钥。

使用方法

use fcm_push_listener::FcmPushListener;

let firebase_app_id = "1:1001234567890:android:2665128ba997ffab830a24";
let firebase_project_id = "myapp-1234567890123";
let firebase_api_key = "aBcDeFgHiJkLmNoPqRsTu01234_aBcD0123456789";
let vapid_key = "BClpBSn3aL7aZ2JZxWB0RrdBqw-5-A7xLoeoxBWdcjxnby4MFvTG8nIa1KHmSY2-cmCAySR4PoCcOZtW18aXNw1";

let registration = fcm_push_listener::register(
    firebase_app_id,
    firebase_project_id,
    firebase_api_key,
    vapid_key).await?;

// Send registration.fcm_token to the server to allow it to send push messages to you.

let mut listener = FcmPushListener::create(
    registration,
    |message: FcmMessage| {
        println!("Message JSON: {}", message.payload_json);
        println!("Persistent ID: {:?}", message.persistent_id);
    },
    |err| { eprintln!("{:?}", err) },
    vec!["0:1677356129944104%7031b2e6f9fd7ecd".to_owned()]);
listener.connect().await?;

您需要保存接收到的消息的持久 ID,然后在下一次调用 connect() 时传入。这样,您就确认了消息的接收,并避免了再次触发它们。

注册需要解密推送消息的秘密;将其存储在安全位置,并在下一次调用 connect() 时重复使用。 Registration 被标记为 SerializeDeserialize,因此您可以直接使用它。

示例 payload_json

{
    "data": {
        "myProp": "myValue"
    },
    "from": "1001234567890",
    "priority": "normal",
    "fcmMessageId": "2cca9428-b164-401c-be3b-e01d8bce6dcd"
}

data 属性包含推送的对象。您可以使用您选择的任何库进行 JSON 解析。

取消

由于 connect() 返回一个 Future 并且运行时间较长,我建议从任务中创建并启动监听器。然后,您可以取消/中止任务以停止推送监听器,并且您的应用程序可以自由地在主线程上执行其他活动。

例如,您可以设置一个服务来管理推送监听器

struct PushService {
    task: Option<JoinHandle<()>>,
    some_state: String,
}

impl PushService {
    pub fn new() -> Self {
        PushService {
            task: None,
            some_state: "abc".to_owned()
        }
    }

    pub fn start(&mut self) {
        let some_state = self.some_state.clone();

        self.task = Some(tokio::task::spawn(async move {
            let registration = /* Get registration from storage or call fcm_push_listener::register() */;

            let mut listener = FcmPushListener::create(
                registration,
                |message: FcmMessage| {
                    println!("Captured state: {}", some_state);
        
                    println!("Message JSON: {}", message.payload_json);
                    println!("Persistent ID: {:?}", message.persistent_id);
                },
                vec![]);

            let result = listener.connect().await;
            if let Err(err) = result {
                eprintln!("{:?}", err);
            }
        }));
    }

    pub fn stop(&mut self) {
        if let Some(task) = &self.task {
            task.abort();
            self.task = None;
        }
    }
}

然后保留一个PushService实例,并在需要取消时调用stop()

实现

依赖项

  • tokio 用于异步/TCP。
  • rustls / tokio-rustls 用于推送监听器的TLS连接。
  • reqwest 用于HTTP调用。
  • prost 用于protobuf。
  • ece 用于创建Web推送密钥对和解密消息。

注册()

  1. 调用 https://android.clients.google.com/checkin 获取Android ID。
  2. 调用 https://android.clients.google.com/c2dm/register3 在GCM中进行注册。给您一个GCM令牌和一个安全令牌。(其他库有时将GCM令牌称为ACG令牌)
  3. 调用 https://firebaseinstallations.googleapis.com/v1/projects/{project_id}/installations 获取Firebase安装令牌。
  4. 使用ece的旧版aesgcm模式创建一个加密密钥对。
  5. 调用 https://fcmregistrations.googleapis.com/v1/projects/{project_id}/registrations 进行最终的FCM注册并获取FCM令牌。

FcmPushListener.连接()

  1. 进行另一个checkin调用以保持我们的“设备”最新。
  2. mtalk.google.com:5228 建立TLS/TCP连接,并发送通过protobuf编码的信息,使用生成的设备ID和我们看到的持久ID列表进行登录。
  3. 保持套接字连接打开以监听推送消息。

消息

当推送消息到达时,它使用protobuf解析出有效载荷和元数据,然后使用注册中存储的私钥和认证密钥解密有效载荷并将其解码为UTF-8字符串。然后它调用提供的闭包,传递JSON有效载荷和持久ID。

重连

如果连接在成功建立后被关闭,它将自动尝试重新打开连接。

致谢

这是基于Matthieu Lemoine的NPM包 push-receiver。他的逆向工程努力非常英勇!

构建设置

  1. 前往 https://github.com/protocolbuffers/protobuf/releases ,找到最新稳定版,然后从protoc-{version}-{platform}.zip中提取protoc.exe并将其放入路径。
  2. 设置OpenSSL。对于Windows,从 https://slproweb.com/products/Win32OpenSSL.html 安装并设置环境变量 OPENSSL_DIRC:\Program Files\OpenSSL-Win64(或您安装它的位置)

依赖项

~16–30MB
~563K SLoC