Najlepsze praktyki dotyczące zarządzania tokenami rejestracyjnymi FCM

Jeśli używasz interfejsów API FCM do programowego tworzenia żądań wysyłania, może się okazać, że z biegiem czasu marnujesz zasoby, wysyłając wiadomości do nieaktywnych urządzeń z nieaktualnymi tokenami rejestracji. Ta sytuacja może mieć wpływ na dane o dostarczeniu wiadomości raportowane w konsoli Firebase lub dane eksportowane do BigQuery, objawiając się drastycznym (ale w rzeczywistości nieważnym) spadkiem współczynnika dostarczania. W tym przewodniku omówiono pewne środki, które możesz podjąć, aby zapewnić skuteczne kierowanie wiadomości i prawidłowe raportowanie dostaw.

Nieaktualne i wygasłe tokeny rejestracyjne

Nieaktualne tokeny rejestracyjne to tokeny powiązane z nieaktywnymi urządzeniami, które nie łączyły się z FCM od ponad miesiąca. W miarę upływu czasu prawdopodobieństwo ponownego połączenia urządzenia z FCM staje się coraz mniejsze. Jest mało prawdopodobne, aby wysłane wiadomości i rozwinięcia tematów dotyczące tych przestarzałych tokenów kiedykolwiek zostały dostarczone.

Istnieje kilka powodów, dla których token może stać się nieaktualny. Na przykład urządzenie, z którym powiązany jest token, może zostać utracone, zniszczone lub odłożone do magazynu i zapomniane.

Kiedy nieaktualne tokeny osiągną 270 dni bezczynności, FCM uzna je za tokeny wygasłe . Po wygaśnięciu tokena FCM oznacza go jako nieważny i odrzuca wysyłanie do niego. Jednak FCM wydaje nowy token dla instancji aplikacji w rzadkich przypadkach, gdy urządzenie ponownie się połączy i aplikacja zostanie otwarta.

Podstawowe najlepsze praktyki

Istnieje kilka podstawowych praktyk, których należy przestrzegać w każdej aplikacji korzystającej z interfejsów API FCM do programowego tworzenia żądań wysyłania. Główne najlepsze praktyki to:

  • Odzyskaj tokeny rejestracyjne z FCM i przechowuj je na swoim serwerze. Ważną rolą serwera jest śledzenie tokena każdego klienta i utrzymywanie aktualnej listy aktywnych tokenów. Zdecydowanie zalecamy wdrożenie znacznika czasu tokena w kodzie i serwerach oraz regularne aktualizowanie tego znacznika czasu.
  • Utrzymuj świeżość tokenów i usuwaj nieaktualne tokeny. Oprócz usuwania tokenów, które FCM nie uważa już za ważne, możesz chcieć monitorować inne oznaki, że tokeny stały się nieaktualne i aktywnie je usuwać. W tym przewodniku omówiono niektóre możliwości osiągnięcia tego celu.

Pobieraj i przechowuj tokeny rejestracyjne

Podczas pierwszego uruchomienia aplikacji zestaw FCM SDK generuje token rejestracji dla instancji aplikacji klienckiej. Jest to token, który należy uwzględnić w żądaniach ukierunkowanego wysyłania z interfejsu API lub dodać do subskrypcji tematów w celu kierowania na tematy.

Zdecydowanie zalecamy, aby Twoja aplikacja pobrała ten token przy pierwszym uruchomieniu i zapisała go na serwerze aplikacji wraz ze sygnaturą czasową . Ten znacznik czasu musi zostać zaimplementowany przez Twój kod i Twoje serwery, ponieważ nie jest udostępniany przez zestawy SDK FCM.

Ważne jest również, aby zapisać token na serwerze i aktualizować znacznik czasu za każdym razem, gdy się zmienia, 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 staje się ponownie aktywna po wygaśnięciu istniejącego tokena FCM

Przykład: przechowuj tokeny i znaczniki czasu w Cloud Firestore

Na przykład możesz użyć Cloud Firestore do przechowywania tokenów w kolekcji o nazwie fcmTokens . Każdy identyfikator dokumentu w kolekcji odpowiada identyfikatorowi użytkownika, a dokument przechowuje bieżący token rejestracji i jego ostatnią aktualizację sygnatury czasowej. Użyj funkcji set , jak pokazano w tym przykładzie Kotlina:

    /**
     * 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)
    }

Za każdym razem, gdy token jest pobierany, jest on przechowywany w Cloud Firestore, wywołując 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()
            }
        }

Utrzymuj świeżość tokenów i usuwaj nieaktualne tokeny

Określenie, czy token jest świeży, czy nieaktualny, nie zawsze jest proste. Aby uwzględnić wszystkie przypadki, należy przyjąć próg określający, kiedy tokeny są nieaktualne. 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ż jeden miesiąc prawdopodobnie będzie urządzeniem nieaktywnym; w przeciwnym razie aktywne urządzenie odświeżyłoby swój token.

W zależności od przypadku użycia jeden miesiąc może być za krótki lub za długi, więc od Ciebie zależy określenie kryteriów, które będą dla Ciebie odpowiednie.

Wykrywaj nieprawidłowe odpowiedzi tokenów z zaplecza FCM

Upewnij się, że wykryłeś nieprawidłowe odpowiedzi na tokeny z FCM i zareaguj, usuwając z systemu wszystkie tokeny rejestracyjne, o których wiadomo, że są nieważne lub wygasły. W przypadku interfejsu API HTTP v1 te komunikaty o błędach mogą wskazywać, że żądanie wysłania było skierowane do 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 którąkolwiek z tych odpowiedzi dla docelowego tokena, możesz bezpiecznie usunąć swój rekord tego tokena, ponieważ nigdy więcej nie będzie on ważny. Na przykład, aby usunąć nieprawidłowe tokeny z Cloud Firestore, możesz wdrożyć i uruchomić funkcję podobną do poniższej:

    // 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 zwróci nieprawidłową odpowiedź na token tylko wtedy, gdy token wygaśnie po 270 dniach lub jeśli klient jawnie się wyrejestruje. Jeśli chcesz dokładniej śledzić nieaktualność zgodnie z własnymi definicjami, możesz proaktywnie usuwać nieaktualne tokeny rejestracji .

Regularnie aktualizuj tokeny

Zalecamy okresowe pobieranie i aktualizowanie wszystkich tokenów rejestracyjnych na serwerze. Wymaga to:

  • Dodaj logikę aplikacji do aplikacji klienckiej, aby pobrać bieżący token za pomocą odpowiedniego wywołania interfejsu API (takiego jak token(completion): w przypadku platform Apple lub getToken() w przypadku systemu Android), a następnie wyślij bieżący token do serwera aplikacji w celu przechowywania (za pomocą znak czasu). Może to być miesięczne zadanie skonfigurowane tak, aby obejmowało wszystkich klientów lub tokeny.
  • Dodaj logikę serwera, aby regularnie aktualizować sygnaturę czasową tokenu, niezależnie od tego, czy token uległ zmianie.

Przykład logiki systemu Android do aktualizowania tokenów przy użyciu WorkManager można znaleźć w artykule Zarządzanie tokenami przesyłania wiadomości w chmurze w blogu Firebase.

Niezależnie od tego, jaki schemat czasowy stosujesz, pamiętaj o okresowej aktualizacji tokenów. Częstotliwość aktualizacji raz na miesiąc zapewnia dobrą równowagę pomiędzy wpływem na baterię a wykrywaniem nieaktywnych tokenów rejestracyjnych. Wykonując to odświeżenie, zapewniasz również, że każde urządzenie, które stanie się nieaktywne, odświeży swoją rejestrację, gdy ponownie stanie się aktywne. Wykonywanie odświeżania częściej niż co tydzień nie przynosi żadnych korzyści.

Usuń nieaktualne tokeny rejestracyjne

Przed wysłaniem wiadomości na urządzenie upewnij się, że sygnatura czasowa tokena rejestracji urządzenia mieści się w okresie okna nieaktualności. Na przykład możesz zaimplementować Cloud Functions dla Firebase, aby codziennie sprawdzać, czy sygnatura czasowa mieści się w zdefiniowanym okresie okna nieaktualności, np. const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30; a następnie usuń 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(); });
});

Anuluj subskrypcję nieaktualnych tokenów z tematów

Jeśli korzystasz z tematów, możesz także chcieć wyrejestrować nieaktualne tokeny z tematów, do których są subskrybowane. Obejmuje to dwa kroki:

  1. Twoja aplikacja powinna ponownie subskrybować tematy raz w miesiącu oraz za każdym razem, gdy zmieni się token rejestracji. Tworzy to rozwiązanie samonaprawiające się, w którym subskrypcje pojawiają się automatycznie ponownie, gdy aplikacja ponownie stanie się aktywna.
  2. Jeśli instancja aplikacji jest bezczynna przez jeden miesiąc (lub Twój własny okres nieaktualności), powinieneś anulować jej subskrypcję tematów za pomocą pakietu Firebase Admin SDK, aby usunąć mapowanie tokenu na temat z zaplecza FCM.

Zaletą tych dwóch kroków jest to, że fanouty będą następować szybciej, ponieważ jest mniej nieaktualnych tokenów, do których można się rozdzielić, a nieaktualne instancje aplikacji zostaną automatycznie ponownie subskrybowane, gdy staną się ponownie aktywne.

Zmierz skuteczność dostawy

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 z dużą liczbą subskrybentów; jeśli część tych subskrybentów jest w rzeczywistości nieaktywna, wpływ na statystyki dostaw może z czasem być znaczący.

Zanim skierujesz wiadomości na token, rozważ:

  • Czy Google Analytics, dane zebrane w BigQuery lub inne sygnały śledzące wskazują, że token jest aktywny?
  • Czy poprzednie próby dostarczenia kończyły się niepowodzeniem przez dłuższy czas?
  • Czy w ciągu ostatniego miesiąca token rejestracyjny został zaktualizowany na Twoich serwerach?
  • Czy w przypadku urządzeń z systemem Android interfejs API danych FCM zgłasza wysoki procent niepowodzeń dostarczania wiadomości z powodu droppedDeviceInactive ?

Aby uzyskać więcej informacji na temat dostarczania, zobacz Omówienie dostarczania wiadomości .