Các phương pháp hay nhất để quản lý mã thông báo đăng ký FCM

Nếu sử dụng API FCM để xây dựng yêu cầu gửi theo chương trình, bạn có thể nhận thấy rằng, theo thời gian, bạn đang lãng phí tài nguyên khi gửi tin nhắn đến các thiết bị không hoạt động có mã thông báo đăng ký cũ. Tình huống này có thể ảnh hưởng đến dữ liệu gửi tin nhắn được báo cáo trong bảng điều khiển Firebase hoặc dữ liệu được xuất sang BigQuery, hiển thị dưới dạng tỷ lệ gửi giảm đáng kể (nhưng không thực sự hợp lệ). Hướng dẫn này thảo luận về một số biện pháp bạn có thể thực hiện để giúp đảm bảo nhắm mục tiêu tin nhắn hiệu quả và báo cáo gửi hợp lệ.

Mã thông báo đăng ký cũ và hết hạn

Mã thông báo đăng ký cũ là mã thông báo được liên kết với các thiết bị không hoạt động chưa kết nối với FCM trong hơn một tháng. Thời gian trôi qua, khả năng thiết bị kết nối lại với FCM ngày càng ít đi. Việc gửi tin nhắn và chia sẻ chủ đề cho các mã thông báo cũ này khó có thể được gửi.

Có một số lý do khiến mã thông báo có thể trở nên cũ. Ví dụ: thiết bị mà mã thông báo được liên kết có thể bị mất, bị phá hủy hoặc được đưa vào bộ lưu trữ và bị lãng quên.

Khi mã thông báo cũ đạt đến 270 ngày không hoạt động, FCM sẽ coi chúng là mã thông báo đã hết hạn . Khi mã thông báo hết hạn, FCM sẽ đánh dấu nó là không hợp lệ và từ chối gửi tới nó. Tuy nhiên, FCM phát hành mã thông báo mới cho phiên bản ứng dụng trong trường hợp hiếm hoi thiết bị kết nối lại và ứng dụng được mở.

Các phương pháp hay nhất cơ bản

Có một số phương pháp cơ bản mà bạn nên tuân theo trong bất kỳ ứng dụng nào sử dụng API FCM để xây dựng yêu cầu gửi theo chương trình. Các phương pháp hay nhất chính là:

  • Truy xuất mã thông báo đăng ký từ FCM và lưu trữ chúng trên máy chủ của bạn. Vai trò quan trọng của máy chủ là theo dõi mã thông báo của từng khách hàng và giữ danh sách cập nhật các mã thông báo đang hoạt động. Chúng tôi thực sự khuyên bạn nên triển khai dấu thời gian mã thông báo trong mã và máy chủ của mình, đồng thời cập nhật dấu thời gian này theo định kỳ.
  • Duy trì độ mới của mã thông báo và loại bỏ mã thông báo cũ. Ngoài việc xóa các token mà FCM coi là không còn hợp lệ, bạn có thể muốn theo dõi các dấu hiệu khác cho thấy các token đã trở nên cũ và chủ động xóa chúng. Hướng dẫn này thảo luận về một số lựa chọn của bạn để đạt được điều này.

Truy xuất và lưu trữ mã thông báo đăng ký

Khi khởi động ứng dụng lần đầu, FCM SDK sẽ tạo mã thông báo đăng ký cho phiên bản ứng dụng khách. Đây là mã thông báo mà bạn phải đưa vào các yêu cầu gửi được nhắm mục tiêu từ API hoặc thêm vào đăng ký chủ đề để nhắm mục tiêu theo chủ đề.

Chúng tôi thực sự khuyên ứng dụng của bạn nên truy xuất mã thông báo này khi khởi động lần đầu và lưu nó vào máy chủ ứng dụng cùng với dấu thời gian . Dấu thời gian này phải được mã và máy chủ của bạn triển khai vì nó không được FCM SDK cung cấp cho bạn.

Ngoài ra, điều quan trọng là lưu mã thông báo vào máy chủ và cập nhật dấu thời gian bất cứ khi nào dấu thời gian thay đổi, chẳng hạn như khi:

  • Ứng dụng được khôi phục trên thiết bị mới
  • Người dùng gỡ cài đặt hoặc cài đặt lại ứng dụng
  • Người dùng xóa dữ liệu ứng dụng
  • Ứng dụng sẽ hoạt động trở lại sau khi FCM hết mã thông báo hiện có

Ví dụ: lưu trữ mã thông báo và dấu thời gian trong Cloud Firestore

Ví dụ: bạn có thể sử dụng Cloud Firestore để lưu trữ mã thông báo trong bộ sưu tập có tên fcmTokens . Mỗi ID tài liệu trong bộ sưu tập tương ứng với một ID người dùng và tài liệu lưu trữ mã thông báo đăng ký hiện tại cũng như dấu thời gian được cập nhật lần cuối. Sử dụng hàm set như trong ví dụ về Kotlin này:

    /**
     * Persist token to third-party servers.
     *
     * Modify this method to associate the user's FCM registration token with any server-side account
     * maintained by your application.
     *
     * @param token The new token.
     */
    private fun sendTokenToServer(token: String?) {
        // If you're running your own server, call API to send token and today's date for the user

        // Example shown below with Firestore
        // Add token and timestamp to Firestore for this user
        val deviceToken = hashMapOf(
            "token" to token,
            "timestamp" to FieldValue.serverTimestamp(),
        )
        // Get user ID from Firebase Auth or your own server
        Firebase.firestore.collection("fcmTokens").document("myuserid")
            .set(deviceToken)
    }

Bất cứ khi nào mã thông báo được truy xuất, nó sẽ được lưu trữ trong Cloud Firestore bằng cách gọi sendTokenToServer :

    /**
     * Called if the FCM registration token is updated. This may occur if the security of
     * the previous token had been compromised. Note that this is called when the
     * FCM registration token is initially generated so this is where you would retrieve the token.
     */
    override fun onNewToken(token: String) {
        Log.d(TAG, "Refreshed token: $token")

        // If you want to send messages to this application instance or
        // manage this apps subscriptions on the server side, send the
        // FCM registration token to your app server.
        sendTokenToServer(token)
    }
        var token = Firebase.messaging.token.await()

        // Check whether the retrieved token matches the one on your server for this user's device
        val preferences = this.getPreferences(Context.MODE_PRIVATE)
        val tokenStored = preferences.getString("deviceToken", "")
        lifecycleScope.launch {
            if (tokenStored == "" || tokenStored != token)
            {
                // If you have your own server, call API to send the above token and Date() for this user's device

                // Example shown below with Firestore
                // Add token and timestamp to Firestore for this user
                val deviceToken = hashMapOf(
                    "token" to token,
                    "timestamp" to FieldValue.serverTimestamp(),
                )

                // Get user ID from Firebase Auth or your own server
                Firebase.firestore.collection("fcmTokens").document("myuserid")
                    .set(deviceToken).await()
            }
        }

Duy trì độ mới của mã thông báo và xóa mã thông báo cũ

Việc xác định xem mã thông báo là mới hay cũ không phải lúc nào cũng đơn giản. Để giải quyết tất cả các trường hợp, bạn nên áp dụng một ngưỡng khi bạn coi mã thông báo đã cũ. Theo mặc định, FCM coi mã thông báo là cũ nếu phiên bản ứng dụng của nó không được kết nối trong một tháng. Bất kỳ mã thông báo nào cũ hơn một tháng đều có thể là thiết bị không hoạt động; nếu không thì một thiết bị đang hoạt động sẽ làm mới mã thông báo của nó.

Tùy thuộc vào trường hợp sử dụng của bạn, một tháng có thể quá ngắn hoặc quá dài, do đó, bạn phải xác định tiêu chí phù hợp với mình.

Phát hiện phản hồi mã thông báo không hợp lệ từ phần phụ trợ FCM

Đảm bảo phát hiện phản hồi mã thông báo không hợp lệ từ FCM và phản hồi bằng cách xóa khỏi hệ thống của bạn mọi mã thông báo đăng ký được xác định là không hợp lệ hoặc đã hết hạn. Với API HTTP v1, các thông báo lỗi này có thể cho biết rằng yêu cầu gửi của bạn đã nhắm mục tiêu các mã thông báo không hợp lệ hoặc đã hết hạn:

  • UNREGISTERED (HTTP 404)
  • INVALID_ARGUMENT (HTTP 400)

Nếu bạn chắc chắn rằng tải trọng tin nhắn là hợp lệ và bạn nhận được một trong những phản hồi này cho mã thông báo được nhắm mục tiêu thì việc xóa bản ghi mã thông báo này của bạn là an toàn vì nó sẽ không bao giờ hợp lệ nữa. Ví dụ: để xóa mã thông báo không hợp lệ khỏi Cloud Firestore, bạn có thể triển khai và chạy một chức năng như sau:

    // Registration token comes from the client FCM SDKs
    const registrationToken = 'YOUR_REGISTRATION_TOKEN';

    const message = {
    data: {
        // Information you want to send inside of notification
    },
    token: registrationToken
    };

    // Send message to device with provided registration token
    getMessaging().send(message)
    .then((response) => {
        // Response is a message ID string.
    })
    .catch((error) => {
        // Delete token for user if error code is UNREGISTERED or INVALID_ARGUMENT.
        if (errorCode == "messaging/registration-token-not-registered") {
            // If you're running your own server, call API to delete the
            token for the user

            // Example shown below with Firestore
            // Get user ID from Firebase Auth or your own server
            Firebase.firestore.collection("fcmTokens").document(user.uid).delete()
        }
    });

FCM sẽ chỉ trả về phản hồi mã thông báo không hợp lệ nếu mã thông báo hết hạn sau 270 ngày hoặc nếu khách hàng chưa đăng ký rõ ràng. Nếu cần theo dõi chính xác hơn độ cũ theo định nghĩa của riêng mình, bạn có thể chủ động loại bỏ các token đăng ký cũ .

Cập nhật token thường xuyên

Chúng tôi khuyên bạn nên truy xuất và cập nhật định kỳ tất cả các mã thông báo đăng ký trên máy chủ của mình. Điều này đòi hỏi bạn phải:

  • Thêm logic ứng dụng vào ứng dụng khách của bạn để truy xuất mã thông báo hiện tại bằng lệnh gọi API thích hợp (chẳng hạn như token(completion): cho nền tảng Apple hoặc getToken() cho Android), sau đó gửi mã thông báo hiện tại đến máy chủ ứng dụng của bạn để lưu trữ (với dấu thời gian). Đây có thể là công việc hàng tháng được định cấu hình để đáp ứng tất cả khách hàng hoặc mã thông báo.
  • Thêm logic máy chủ để cập nhật dấu thời gian của mã thông báo theo định kỳ, bất kể mã thông báo có thay đổi hay không.

Để biết ví dụ về logic Android để cập nhật mã thông báo bằng WorkManager , hãy xem Quản lý mã thông báo qua đám mây trên blog Firebase.

Dù bạn tuân theo mô hình thời gian nào, hãy đảm bảo cập nhật mã thông báo định kỳ. Tần suất cập nhật một lần mỗi tháng tạo ra sự cân bằng tốt giữa tác động của pin và việc phát hiện mã thông báo đăng ký không hoạt động. Bằng cách thực hiện việc làm mới này, bạn cũng đảm bảo rằng mọi thiết bị không hoạt động sẽ làm mới đăng ký của nó khi thiết bị hoạt động trở lại. Không có lợi ích gì khi làm mới thường xuyên hơn hàng tuần.

Xóa mã thông báo đăng ký cũ

Trước khi gửi tin nhắn đến một thiết bị, hãy đảm bảo rằng dấu thời gian của mã thông báo đăng ký của thiết bị nằm trong khoảng thời gian ổn định của bạn. Ví dụ: bạn có thể triển khai Chức năng đám mây cho Firebase để chạy kiểm tra hàng ngày nhằm đảm bảo rằng dấu thời gian nằm trong khoảng thời gian ổn định được xác định, chẳng hạn như const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; và sau đó xóa mã thông báo cũ:

exports.pruneTokens = functions.pubsub.schedule('every 24 hours').onRun(async (context) => {
  // Get all documents where the timestamp exceeds is not within the past month
  const staleTokensResult = await admin.firestore().collection('fcmTokens')
      .where("timestamp", "<", Date.now() - EXPIRATION_TIME)
      .get();
  // Delete devices with stale tokens
  staleTokensResult.forEach(function(doc) { doc.ref.delete(); });
});

Hủy đăng ký mã thông báo cũ khỏi chủ đề

Nếu bạn sử dụng các chủ đề, bạn cũng có thể muốn hủy đăng ký các mã thông báo cũ khỏi các chủ đề mà chúng đã đăng ký. Điều này bao gồm hai bước:

  1. Ứng dụng của bạn nên đăng ký lại các chủ đề mỗi tháng một lần và bất cứ khi nào mã thông báo đăng ký thay đổi. Điều này tạo thành một giải pháp tự phục hồi, trong đó các đăng ký sẽ tự động xuất hiện lại khi ứng dụng hoạt động trở lại.
  2. Nếu một phiên bản ứng dụng không hoạt động trong một tháng (hoặc khoảng thời gian ngừng hoạt động của riêng bạn), bạn nên hủy đăng ký phiên bản đó khỏi các chủ đề bằng cách sử dụng SDK quản trị Firebase để xóa mã thông báo tới ánh xạ chủ đề khỏi phần phụ trợ FCM.

Lợi ích của hai bước này là việc phân phát của bạn sẽ diễn ra nhanh hơn vì có ít mã thông báo cũ hơn để phân phát và các phiên bản ứng dụng cũ của bạn sẽ tự động đăng ký lại sau khi chúng hoạt động trở lại.

Đo lường sự thành công của việc phân phối

Để có được bức tranh chính xác nhất về việc gửi tin nhắn, tốt nhất bạn chỉ nên gửi tin nhắn đến các phiên bản ứng dụng được sử dụng tích cực. Điều này đặc biệt quan trọng nếu bạn thường xuyên gửi tin nhắn đến các chủ đề có số lượng người đăng ký lớn; nếu một phần trong số những người đăng ký đó thực sự không hoạt động thì tác động lên số liệu thống kê phân phối của bạn có thể đáng kể theo thời gian.

Trước khi nhắm mục tiêu tin nhắn đến mã thông báo, hãy xem xét:

  • Google Analytics, dữ liệu được thu thập trong BigQuery hoặc các tín hiệu theo dõi khác có cho biết mã thông báo đang hoạt động không?
  • Những lần giao hàng trước đó có thất bại liên tục trong một khoảng thời gian không?
  • Mã thông báo đăng ký đã được cập nhật trên máy chủ của bạn trong tháng qua chưa?
  • Đối với các thiết bị Android, API dữ liệu FCM có báo cáo tỷ lệ lỗi gửi tin nhắn cao do droppedDeviceInactive ?

Để biết thêm thông tin về cách gửi, hãy xem Tìm hiểu cách gửi tin nhắn .