Sprawdzone metody zarządzania tokenami rejestracji w FCM

Jeśli do automatycznego tworzenia żądań wysyłania używasz interfejsów API, z czasem możesz zauważyć, że marnujesz zasoby, wysyłając wiadomości na nieaktywne urządzenia z nieaktualnymi tokenami rejestracji.FCM Może to wpłynąć na dane o dostarczaniu wiadomości raportowane w konsoli Firebase lub dane eksportowane do BigQuery, powodując gwałtowny (ale nieprawdziwy) spadek wskaźników dostarczania. W tym przewodniku omawiamy niektóre działania, które możesz podjąć, aby zapewnić skuteczne kierowanie wiadomości i prawidłowe raportowanie dostarczania.

Nieaktualne i wygasłe tokeny rejestracji

Nieaktualne tokeny rejestracji to tokeny powiązane z nieaktywnymi urządzeniami, które nie łączyły się z usługą FCM od ponad miesiąca. Z czasem prawdopodobieństwo ponownego połączenia urządzenia z FCM maleje. Wiadomości wysyłane do tych nieaktualnych tokenów i rozsyłane do tematów prawdopodobnie nigdy nie zostaną dostarczone.

Token może stracić ważność z kilku powodów. Na przykład urządzenie, z którym jest powiązany token, może zostać zgubione, zniszczone lub schowane i zapomniane.

Gdy nieaktywne tokeny osiągną 270 dni nieaktywności, FCM uzna je za wygasłe. Gdy token wygaśnie, FCM oznacza go jako nieprawidłowy i odrzuca wysyłane do niego wiadomości. Jednak w rzadkich przypadkach, gdy urządzenie ponownie nawiąże połączenie i aplikacja zostanie otwarta, FCM wyda nowy token dla instancji aplikacji.

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 zasad. Najważniejsze sprawdzone metody:

  • Pobierz tokeny rejestracji z FCM i zapisz je na serwerze. Ważną rolą serwera jest śledzenie tokena każdego klienta i prowadzenie aktualnej listy aktywnych tokenów. Zdecydowanie zalecamy zaimplementowanie w kodzie i na serwerach sygnatury czasowej tokena oraz regularne aktualizowanie tej sygnatury.
  • Utrzymuj aktualność tokenów i usuwaj nieaktualne tokeny. Oprócz usuwania tokenów, które FCM nie uważa już za prawidłowe, możesz monitorować inne oznaki, że tokeny stały się nieaktualne, i usuwać je proaktywnie. W tym przewodniku omawiamy niektóre z dostępnych opcji.

Pobieranie i przechowywanie tokenów rejestracji

Podczas pierwszego uruchomienia aplikacji pakiet SDK FCM generuje token rejestracyjny dla instancji aplikacji klienta. Jest to token, który musisz uwzględnić w żądaniach wysyłania kierowanego z interfejsu API lub dodać do subskrypcji tematów, aby kierować na tematy.

Zdecydowanie zalecamy, aby aplikacja pobierała ten token przy pierwszym uruchomieniu i zapisywała go na serwerze aplikacji wraz ze znacznikiem czasu. Ten sygnatura czasowa musi być zaimplementowana w Twoim kodzie i na Twoich serwerach, ponieważ nie jest dostarczana przez pakiety SDK FCM.

Ważne jest też, aby zapisać token na serwerze i aktualizować sygnaturę czasową za każdym razem, gdy się zmieni, np. gdy:

  • Aplikacja zostanie przywrócona na nowym urządzeniu.
  • Użytkownik odinstaluje lub ponownie zainstaluje aplikację
  • Użytkownik usuwa dane aplikacji
  • Aplikacja ponownie stanie się aktywna po wygaśnięciu obecnego tokena FCM.

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

Możesz na przykład 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 sygnaturę czasową ostatniej aktualizacji. Użyj funkcji set, jak pokazano w tym przykładzie w Kotlinie:

    /**
     * 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 przez wywołanie funkcji 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()
            }
        }

Dbanie o aktualność tokenów i usuwanie nieaktualnych tokenów

Określenie, czy token jest aktualny czy nie, nie zawsze jest proste. Aby uwzględnić wszystkie przypadki, należy przyjąć próg, po przekroczeniu którego tokeny będą uznawane za nieaktualne. Domyślnie FCM uznaje token za nieaktualny, jeśli instancja aplikacji nie łączyła się przez miesiąc. Każdy token starszy niż miesiąc prawdopodobnie należy do nieaktywnego urządzenia, ponieważ aktywne urządzenie odświeżyłoby token.

W zależności od przypadku użycia miesiąc może być zbyt krótki lub zbyt długi, dlatego to Ty musisz określić kryteria, które Ci odpowiadają.

wykrywać nieprawidłowe odpowiedzi dotyczące tokenów z backendu FCM;

Wykrywaj nieprawidłowe odpowiedzi tokena z FCM i reaguj na nie, usuwając z systemu wszystkie tokeny rejestracyjne, które są nieprawidłowe lub wygasły. W przypadku interfejsu HTTP v1 API te komunikaty o błędach mogą oznaczać, że żądanie wysyłania było kierowane na nieprawidłowe lub wygasłe tokeny:

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

Jeśli masz pewność, że ładunek wiadomości jest prawidłowy, a w przypadku wybranego tokena otrzymasz jedną z tych odpowiedzi, możesz bezpiecznie usunąć rekord tego tokena, ponieważ nigdy więcej nie będzie on ważny. Aby na przykład usunąć nieprawidłowe tokeny z Cloud Firestore, możesz wdrożyć i uruchomić funkcję podobną do tej:

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

Regularne aktualizowanie tokenów

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

  • Dodaj do aplikacji klienta logikę pobierania bieżącego tokena 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 (z sygnaturą czasową). Może to być zadanie miesięczne skonfigurowane tak, aby obejmowało wszystkich klientów lub tokeny.
  • Dodaj logikę serwera, aby regularnie aktualizować sygnaturę czasową tokena, niezależnie od tego, czy token uległ zmianie.

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

Niezależnie od tego, jakiego wzorca czasowego używasz, pamiętaj o okresowej aktualizacji tokenów. Częstotliwość aktualizacji raz w miesiącu zapewnia dobrą równowagę między wpływem na baterię a wykrywaniem nieaktywnych tokenów rejestracji. Odświeżając w ten sposób, masz też pewność, że każde urządzenie, które stanie się nieaktywne, odświeży rejestrację, gdy znów będzie aktywne. Odświeżanie częstsze niż raz w tygodniu nie przynosi żadnych korzyści.

Usuwanie nieaktualnych tokenów rejestracji

Zanim wyślesz wiadomości na urządzenie, upewnij się, że sygnatura czasowa tokena rejestracyjnego urządzenia mieści się w okresie ważności. Możesz na przykład zaimplementować Cloud Functions for Firebase, aby codziennie sprawdzać, czy sygnatura czasowa mieści się w określonym okresie nieaktualności, np. const EXPIRATION_TIME = 1000 * 60 * 60 * 24 * 30;, a następnie usuwać 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 w tematach

Jeśli używasz tematów, możesz też wyrejestrować nieaktualne tokeny z tematów, do których są one subskrybowane. Obejmuje to 2 kroki:

  1. Aplikacja powinna ponownie subskrybować tematy raz w miesiącu i za każdym razem, gdy zmieni się token rejestracji. Dzięki temu powstaje rozwiązanie samonaprawcze, w którym subskrypcje pojawiają się ponownie automatycznie, gdy aplikacja znów staje się aktywna.
  2. Jeśli instancja aplikacji jest nieaktywna przez miesiąc (lub przez wybrany przez Ciebie okres nieaktywności), należy anulować jej subskrypcję tematów za pomocą pakietu Firebase Admin SDK, aby usunąć mapowanie tokena na temat z backendu FCM.

Zaletą tych dwóch kroków jest to, że rozsyłanie będzie szybsze, ponieważ będzie mniej nieaktualnych tokenów, a nieaktywne instancje aplikacji automatycznie ponownie zasubskrybują powiadomienia, gdy znów będą aktywne.

Mierzenie skuteczności dostarczania

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

Zanim zaczniesz kierować wiadomości na token, weź pod uwagę te kwestie:

  • Czy Google Analytics, dane zarejestrowane w BigQuery lub inne sygnały śledzenia wskazują, że token jest aktywny?
  • Czy poprzednie próby dostarczenia nie powiodły się w ciągu pewnego okresu?
  • Czy w ostatnim miesiącu token rejestracji został zaktualizowany na Twoich serwerach?
  • Czy w przypadku urządzeń z Androidem interfejs FCM Data API zgłasza wysoki odsetek nieudanych dostarczeń wiadomości z powodu droppedDeviceInactive?

Więcej informacji o dostarczaniu znajdziesz w artykule Wyjaśnienie dostarczania wiadomości.