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 các yêu cầu gửi theo phương thức lập 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 bằng cách gửi thư đến thiết bị có mã thông báo đăng ký cũ. Trường hợp này có thể ảnh hưởng đến thông báo dữ liệu phân phối được báo cáo trong bảng điều khiển của Firebase hoặc dữ liệu được xuất sang BigQuery, cho thấy sự sụt giảm đáng kể (nhưng không thực sự hợp lệ) về tỷ lệ phân phối. Chiến dịch này hướng dẫn này thảo luận một số biện pháp bạn có thể thực hiện để đảm bảo thông điệp hiệu quả và báo cáo phân phố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 liên kết với những thiết bị không hoạt động và có không kết nối với FCM trong hơn một tháng. Theo thời gian, số lượng thành phần trở nên ít hơn và ít khả năng thiết bị sẽ kết nối lại với FCM. Nội dung gửi và gửi người hâm mộ chủ đề cho các mã thông báo cũ này sẽ ít có khả năng đã gửi.

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

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

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

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

  • Truy xuất mã thông báo đăng ký từ FCM và lưu trữ chúng trên máy chủ. Vai trò quan trọng đối với máy chủ là theo dõi mã thông báo và cập nhật danh sách mã thông báo đang hoạt động. Bạn nên triển khai dấu thời gian của mã thông báo trong mã và máy chủ của bạn, đồ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à xoá các mã thông báo cũ. Ngoài xoá mã thông báo mà FCM không còn hợp lệ, bạn nên để theo dõi các dấu hiệu khác cho thấy mã thông báo đã cũ và xoá chúng một cách chủ động. Hướng dẫn này trình bày một số phương án bạn có thể thực hiện để đạt được mục tiê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 tiên, SDK FCM sẽ tạo một đăng ký mã thông báo cho phiên bản ứng dụng khách. Đây là mã thông báo bạn phải đưa vào gửi các yêu cầu được nhắm mục tiêu từ API hoặc thêm vào gói thuê bao chủ đề để nhắm mục tiêu theo chủ đề.

Ứ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 máy chủ ứng dụng cùng với một dấu thời gian. Dấu thời gian này phải là do mã và máy chủ của bạn triển khai, vì mã không được cung cấp cho bạn bởi SDK FCM.

Ngoài ra, bạn cần phải 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 giá trị này thay đổi, chẳng hạn như khi:

  • Ứng dụng đó được khôi phục trên một 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 xoá dữ liệu ứng dụng
  • Ứng dụng sẽ hoạt động trở lại sau khi FCM hết hạn hiện có mã thông báo

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ể dùng Cloud Firestore để lưu trữ mã thông báo trong một bộ sưu tập có tên là fcmTokens. Mỗi mã tài liệu trong tập hợp tương ứng với một mã nhận dạng 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ập nhật gần đây nhất. Sử dụng hàm set như trong ví dụ sau về Kotlin:

    /**
     * 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ột mã thông báo được truy xuất, mã đó 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à xoá các mã thông báo cũ

Việc xác định xem một mã thông báo là mới hay cũ không phải lúc nào cũng đơn giản. Người nhận bao gồm mọi trường hợp, bạn nên đặt một ngưỡng khi xem xét mã thông báo lỗi thời. Theo mặc định, FCM coi một mã thông báo là đã lỗi thời nếu ứng dụng thực thể chưa được kết nối trong một tháng. Có thể có bất kỳ mã thông báo nào cũ hơn một tháng là thiết bị không hoạt động; nếu không thì một thiết bị đang hoạt động đã làm mới mã thông báo.

Tuỳ theo 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, vì vậy hãy tăng thời gian để xác định tiêu chí phù hợp với bạn.

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 chậm nhất vào xoá 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, những 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 đến 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 hai những phản hồi này đối với một mã thông báo được nhắm mục tiêu, nên việc xoá bản ghi của bạn về thông báo này có thể an toàn vì mã này sẽ không còn hợp lệ nữa. Ví dụ: để xoá mã thông báo không hợp lệ từ Cloud Firestore, bạn có thể triển khai và chạy một hàm 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 đã huỷ đăng ký một cách rõ ràng. Nếu bạn cần thêm theo dõi chính xác tình trạng lỗi thời theo định nghĩa của riêng mình, bạn có thể chủ động xoá các mã thông báo đăng ký cũ.

Thường xuyên cập nhật mã thông báo

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 bạn. Việc này yêu cầu 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 cách sử dụng lệnh gọi API thích hợp (chẳng hạn như token(completion): cho các nền tảng của 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ữ (có dấu thời gian). Đây có thể là một công việc hằng tháng được thiết lập để bao gồm 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 đã thay đổi hay chưa.

Ví dụ về logic của Android để cập nhật mã thông báo bằng WorkManager, xem Quản lý mã thông báo Gửi thông báo qua đám mây trên blog Firebase.

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

Xoá mã thông báo đăng ký cũ

Trước khi gửi thông báo tới 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ý đang trong thời hạn của thời hạn hiệu lực. Ví dụ: bạn có thể triển khai Cloud Functions cho Firebase nhằm chạy quy trình 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 đã xác định về tình trạng lỗi thời, chẳng hạn như const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30;, sau đó xoá các 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(); });
});

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

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

  1. Ứng dụng của bạn sẽ đăng ký lại các chủ đề một lần mỗi tháng và bất cứ khi nào thay đổi mã thông báo đăng ký. Điều này tạo thành một giải pháp tự chữa lành, trong đó các gói thuê bao sẽ tự động xuất hiện lại khi một ứ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 lỗi thời của riêng bạn), bạn nên huỷ đăng ký tài khoản này khỏi các chủ đề bằng cách sử dụng SDK dành cho quản trị viên của Firebase để xoá mã thông báo liên kết với chủ đề khỏi phần phụ trợ FCM.

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

Đo lường khả năng phân phối thành công

Để có được hình ảnh chính xác nhất về việc gửi thư, tốt nhất bạn chỉ nên gửi thông báo cho các phiên bản ứng dụng đang được sử dụng. Điều này đặc biệt quan trọng nếu bạn thường xuyên gửi thông điệp đến các chủ đề có số lượng người đăng ký lớn; nếu một trong số những người đăng ký đó thực sự không hoạt động, sự ảnh hưởng đến nội dung bạn cung cấp có thể mang lại đáng kể theo thời gian.

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

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

Để biết thêm thông tin về việc giao hàng, hãy xem Tìm hiểu về tính năng gửi thư.