Sprawdzone metody zarządzania tokenami rejestracji w FCM

Jeśli używasz interfejsów API FCM do automatycznego tworzenia żądań wysyłania, możesz zauważyć, że z czasem marnujesz zasoby, wysyłając komunikaty do nieaktywnych urządzeń z nieaktualnymi tokenami rejestracji. Ta sytuacja może wpływać na dane dotyczące dostarczania wiadomości raportowane w konsoli Firebase lub na dane wyeksportowane do BigQuery. Liczbę tę może wiązać się ze znacznym (ale w rzeczywistości) nieuzasadnionym spadkiem. W tym przewodniku omawiamy działania, które możesz podjąć, aby zapewnić skuteczne kierowanie wiadomości i prawidłowe raportowanie wyświetlania.

nieaktualne i wygasłe tokeny rejestracji,

Nieaktualne tokeny rejestracji to tokeny powiązane z nieaktywnymi urządzeniami, które od ponad miesiąca nie były połączone z FCM. Z czasem prawdopodobieństwo, że urządzenie ponownie połączy się z FCM, maleje. Wysyłane wiadomości i rozszerzone tematy związane z nieaktualnymi tokenami raczej nie zostaną dostarczone.

Token może stać się nieaktualny z kilku powodów. Na przykład urządzenie, z którym jest powiązany token, może zostać zgubione, zniszczone lub umieszczone w pamięci i zapomniane.

Gdy nieaktualne tokeny będą nieaktywne przez 270 dni, FCM uzna je za wygasłe tokeny. Gdy token wygaśnie, FCM oznacza go jako nieprawidłowy i odrzuca wysyłanie do niego wiadomości. FCM generuje jednak nowy token dla instancji aplikacji w rzadkich przypadkach, gdy urządzenie ponownie połączy się i aplikacja zostanie otwarta.

Podstawowe sprawdzone metody

W każdej aplikacji, która korzysta z interfejsów API FCM do automatycznego tworzenia żądań wysyłania, należy przestrzegać kilku podstawowych metod. Najważniejsze sprawdzone metody:

  • Pobierz tokeny rejestracji z FCM i zapisz je na serwerze. Ważną rolą serwera jest śledzenie tokenów każdego klienta i aktualizowanie listy aktywnych tokenów. Zdecydowanie zalecamy wdrożenie sygnatury czasowej tokena w kodzie i na serwerach oraz regularne aktualizowanie tej sygnatury czasowej.
  • Dbaj o aktualność tokenów i usuwaj nieaktualne tokeny. Oprócz usuwania tokenów, które FCM już nie uznaje za prawidłowe, warto też obserwować inne oznaki tego, że tokeny stały się nieaktualne, i aktywnie je usuwać. Z tego przewodnika dowiesz się, jak to zrobić.

Pobieranie i przechowywanie tokenów rejestracji

Przy pierwszym uruchomieniu aplikacji pakiet SDK FCM generuje token rejestracji dla instancji aplikacji klienckiej. Jest to token, który musisz umieścić w kierowanych żądaniach wysyłania z interfejsu API lub dodać go do subskrypcji tematów, aby kierować reklamy na tematy.

Zdecydowanie zalecamy, aby aplikacja pobierała ten token przy pierwszym uruchomieniu i zapisz go na serwerze aplikacji wraz z sygnaturą czasową. Ta sygnatura czasowa musi zostać zaimplementowana przez Twój kod i Twoje serwery, ponieważ pakiety SDK FCM jej nie udostępniają.

Ważne jest też, aby zapisać token na serwerze i aktualizować sygnaturę czasową po każdej zmianie, na przykład gdy:

  • Aplikacja zostanie przywrócona na nowym urządzeniu
  • użytkownik odinstalowuje lub ponownie instaluje aplikację;
  • Użytkownik czyści dane aplikacji.
  • Aplikacja stanie się ponownie aktywna po wygaśnięciu tokena FCM

Przykład: przechowywanie tokenów i sygnatur czasowych w Cloud Firestore

W Cloud Firestore możesz na przykład przechowywać tokeny w kolekcji o nazwie fcmTokens. Każdy identyfikator dokumentu w kolekcji odpowiada identyfikatorowi użytkownika, a dokument zawiera aktualny token rejestracji i jego ostatnią zaktualizowaną sygnaturę czasową. Użyj funkcji set w sposób pokazany w tym przykładzie 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)
    }

Przy każdym pobieraniu token jest zapisywany w Cloud Firestore przez wywołanie metody 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()
            }
        }

Dbaj o aktualność tokenów i usuwaj nieaktualne tokeny

Ustalenie, czy token jest aktualny czy nie, nie zawsze jest łatwe. Aby uwzględnić wszystkie przypadki, należy wprowadzić próg, po przekroczeniu którego uznajesz, że tokeny są nieaktywne. Domyślnie FCM uważa token za nieaktualny, jeśli jego instancja aplikacji nie była połączona przez miesiąc. Każdy token starszy niż miesiąc prawdopodobnie zostałby nieaktywny, a aktywne urządzenie odświeżyłoby swój token.

W zależności od zastosowania 1 miesiąc może być za krótki lub za długi, więc Ty decydujesz, jakie kryteria Ci odpowiadają.

Wykrywanie nieprawidłowych odpowiedzi tokenów z backendu FCM

Pamiętaj, aby wykryć nieprawidłowe odpowiedzi tokenów z FCM i usuwać z systemu wszystkie tokeny rejestracji, które są nieprawidłowe lub straciły ważność. W interfejsie API HTTP w wersji 1 te komunikaty o błędach mogą wskazywać, że żądanie wysłania dotyczy nieprawidłowych lub wygasłych tokenów:

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

Jeśli masz pewność, że ładunek wiadomości jest prawidłowy i otrzymasz jedną z tych odpowiedzi dla docelowego tokena, możesz bezpiecznie usunąć rekord tego tokena, ponieważ nigdy nie będzie on prawidłowy. Aby na przykład usunąć nieprawidłowe tokeny z Cloud Firestore, możesz wdrożyć i uruchomić taką funkcję:

    // 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 zwraca nieprawidłową odpowiedź tokena tylko wtedy, gdy token wygasł po 270 dniach lub klient wyraźnie się wyrejestrował. Jeśli chcesz dokładniej śledzić brak aktualizacji zgodnie z własnymi definicjami, możesz proaktywnie usuwać nieaktualne tokeny rejestracji.

Regularnie aktualizuj tokeny

Zalecamy okresowe pobieranie i aktualizowanie wszystkich tokenów rejestracji na serwerze. Wymagania:

  • Dodaj logikę aplikacji do aplikacji klienckiej, aby pobrać bieżący token za pomocą odpowiedniego wywołania interfejsu API (np. token(completion): w przypadku platform Apple lub getToken() w przypadku Androida), a następnie wyślij bieżący token na serwer aplikacji w celu zapisania go (z sygnaturą czasową). Może to być miesięczne zadanie skonfigurowane tak, aby obejmowało wszystkie klienty lub tokeny.
  • Dodawaj logikę serwera, aby aktualizować sygnaturę czasową tokena w regularnych odstępach czasu niezależnie od tego, czy token się zmienił.

Przykład logiki Androida do aktualizowania tokenów za pomocą WorkManagera znajdziesz na blogu Firebase w sekcji Managing Cloud Messaging Tokens (Zarządzanie tokenami komunikacji w chmurze).

Niezależnie od tego, jakiego wzorca przestrzegasz, pamiętaj, aby co jakiś czas aktualizować tokeny. Częstotliwość aktualizacji raz na miesiąc zapewnia odpowiednią równowagę między wpływem na baterię a wykrywaniem nieaktywnych tokenów rejestracji. Dzięki temu masz także pewność, że każde nieaktywne urządzenie odświeży rejestrację, gdy stanie się ponownie aktywne. Częstsze odświeżanie nie ma żadnych korzyści.

Usuń nieaktualne tokeny rejestracji

Zanim wyślesz wiadomości do urządzenia, sprawdź, czy sygnatura czasowa tokena rejestracji urządzenia mieści się w okresie braku aktualizacji. Możesz na przykład zaimplementować Cloud Functions dla Firebase, aby codziennie sprawdzać, czy sygnatura czasowa mieści się w określonym okresie braku aktualizacji, np. const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30;, a następnie usunąć nieaktualne tokeny:

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(); });
});

Anulowanie subskrypcji nieaktualnych tokenów z tematów

Jeśli używasz tematów, możesz też wyrejestrować nieaktualne tokeny z tematów, które subskrybują. Ten proces składa się z 2 etapów:

  1. Aplikacja powinna ponownie subskrybować tematy raz w miesiącu i po każdej zmianie tokena rejestracji. Jest to rozwiązanie samoobsługowe, w którym subskrypcje pojawiają się automatycznie, gdy aplikacja ponownie stanie się aktywna.
  2. Jeśli instancja aplikacji jest nieaktywna przez miesiąc (lub masz własny okres braku aktualizacji), anuluj subskrypcję tematów za pomocą pakietu SDK Firebase Admin, aby usunąć token z mapowaniem tematów z backendu FCM.

Zaletą tych 2 kroków jest to, że rozpowszechnianie trwa krócej, ponieważ jest mniej nieaktualnych tokenów, a nieaktualne instancje aplikacji będą automatycznie odnawiane po wznowieniu aktywności.

Zmierz skuteczność wyświetlania

Aby uzyskać najdokładniejszy obraz dostarczania wiadomości, najlepiej wysyłać wiadomości tylko do aktywnie używanych instancji aplikacji. Jest to szczególnie ważne, jeśli regularnie wysyłasz wiadomości na tematy mające dużą liczbę subskrybentów. Jeśli część z nich jest nieaktywna, wpływ na statystyki dostarczania może z czasem znacząco się zmienić.

Zanim skierujesz wiadomości na token, weź pod uwagę te informacje:

  • Czy Google Analytics, dane zebrane w BigQuery lub inne sygnały śledzenia wskazują, że token jest aktywny?
  • Czy wcześniejsze próby dostarczenia wiadomości w danym okresie nie udawały się regularnie?
  • Czy token rejestracji został zaktualizowany na Twoich serwerach w zeszłym miesiącu?
  • Czy w przypadku urządzeń z Androidem interfejs FCM Data API zgłasza wysoki odsetek niepowodzeń dostarczenia wiadomości z powodu droppedDeviceInactive?

Więcej informacji o dostarczaniu wiadomości znajdziesz w artykule Informacje o dostarczaniu wiadomości.