Sprawdzone metody zarządzania tokenami rejestracji w FCM

Jeśli do tworzenia żądań wysyłania używasz interfejsów API FCM, możesz zauważyć, że z czasem marnujesz zasoby, wysyłając wiadomości do nieaktywnych urządzeń z nieaktualnymi tokenami rejestracji. Może to mieć wpływ na dane dotyczące dostarczania wiadomości raportowane w konsoli Firebase lub dane eksportowane do BigQuery, które będą wyglądać jak znaczny (ale nieprawidłowy) spadek współczynników dostarczania. W tym przewodniku znajdziesz informacje o tym, co możesz zrobić, aby zapewnić skuteczne kierowanie wiadomości i prawidłowe raportowanie ich dostarczania.

Nieaktualne i wygasłe tokeny rejestracji

Nieaktualne tokeny rejestracji to tokeny powiązane z nieaktywnymi urządzeniami, które nie były połączone z FCM przez ponad miesiąc. Z upływem czasu prawdopodobieństwo ponownego połączenia urządzenia z FCM będzie się zmniejszać. Wiadomości wysyłane i rozpowszechniane w ramach tych tokenów są mało prawdopodobne.

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

Gdy nieaktualne tokeny osiągną 270 dni nieaktywności, FCM uzna je za nieaktualne tokeny. Gdy token wygaśnie, FCM oznaczy go jako nieprawidłowy i odrzuci wysyłane do niego wiadomości. Jednak w rzadkich przypadkach, gdy urządzenie ponownie nawiąże połączenie i otworzy aplikację, FCM wygeneruje nowy token dla instancji aplikacji.

Podstawowe sprawdzone metody

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

  • Pobieraj tokeny rejestracji z FCM i przechowuj je na serwerze. Ważną rolą serwera jest śledzenie tokenów każdego klienta i utrzymywanie aktualnej listy aktywnych tokenów. Zdecydowanie zalecamy implementację sygnatury czasowej tokena w kodzie i na serwerach oraz aktualizowanie tej sygnatury w regularnych odstępach czasu.
  • Utrzymywanie aktualności tokenów i usuwanie nieaktualnych tokenów. Oprócz usuwania tokenów, które FCM nie uważa już za ważne, warto też zwracać uwagę na inne oznaki tego, że tokeny stały się nieaktualne, i usuwać je w sposób zapobiegawczy. W tym przewodniku omawiamy niektóre z dostępnych opcji.

Pobieranie i przechowywanie tokenów rejestracji

Podczas pierwszego uruchamiania aplikacji pakiet SDK FCM generuje token rejestracji dla instancji aplikacji klienta. Ten token musisz uwzględnić w żądaniach wysyłania ukierunkowanych z interfejsu API lub dodać do subskrypcji tematów, aby kierować reklamy na tematy.

Zdecydowanie zalecamy, aby aplikacja pobierała ten token podczas uruchamiania i zapisywała go na serwerze aplikacji wraz z sygnaturą czasową. Ten sygnaturę czasową musisz zaimplementować w kodzie i na serwerach, ponieważ nie jest ona udostępniana przez pakiety SDK FCM.

Ważne jest też, aby zapisać token na serwerze i zaktualizować sygnaturę czasową, gdy ulegnie ona zmianie, np. gdy:

  • Aplikacja jest przywracana na nowym urządzeniu
  • Użytkownik odinstaluje lub ponownie zainstaluje aplikację.
  • Użytkownik czyści dane aplikacji
  • Aplikacja ponownie stanie się aktywna, gdy FCM wygaśnie jej dotychczasowy token.

Przykład: przechowywanie tokenów i danych o czasie w pliku Cloud Firestore

Możesz na przykład użyć funkcji Cloud Firestore do przechowywania tokenów w kolekcji o nazwie fcmTokens. Każdy identyfikator dokumentu w zbiorze odpowiada identyfikatorowi użytkownika, a dokument przechowuje bieżący token rejestracji i jego sygnaturę czasową ostatniej aktualizacji. Użyj funkcji set w ten sposób:

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

Pobierany token jest 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()
            }
        }

Utrzymywanie tokenów w stanie aktualności i usuwanie nieaktualnych tokenów

Ustalenie, czy token jest aktualny, czy nie, nie zawsze jest proste. Aby uwzględnić wszystkie przypadki, należy określić próg, po przekroczeniu którego tokeny są uważane za stałe. Domyślnie FCM uznaje token za nieaktualny, jeśli instancja aplikacji nie była połączona przez miesiąc. Token starszy niż miesiąc jest prawdopodobnie związany z nieaktywnym urządzeniem. Aktywne urządzenie odświeża swój token.

W zależności od przypadku użycia miesiąc może być za krótki lub za długi, więc to od Ciebie zależy, jakie kryteria będą dla Ciebie odpowiednie.

Wykrywanie nieprawidłowych odpowiedzi z tokenem z backendu FCM

Pamiętaj, aby wykrywać nieprawidłowe odpowiedzi z usług FCM i usuwać z systemu wszystkie tokeny rejestracji, które są nieprawidłowe lub których ważność wygasła. W przypadku interfejsu HTTP w wersji 1 te komunikaty o błędzie mogą wskazywać, że żądanie wysyłania było kierowane do nieprawidłowych lub nieważnych 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 na token kierowany, możesz bezpiecznie usunąć rekord tego tokena, ponieważ nigdy więcej nie będzie on prawidłowy. Aby na przykład usunąć nieprawidłowe tokeny z Cloud Firestore, możesz wdrożyć i uruchomić funkcję o takim kształcie:

    // 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 odpowiedź z nieprawidłowym tokenem tylko wtedy, gdy token wygaśnie po 270 dniach lub jeśli klient zostanie wyraźnie wyrejestrowany. Jeśli chcesz dokładniej śledzić nieaktualne tokeny rejestracji zgodnie z definicjami własnymi, możesz usunąć nieaktualne tokeny rejestracji.

Regularnie aktualizuj tokeny

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

  • Dodaj w aplikacji klienta logikę, która umożliwia pobranie 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 do przechowywania na serwerze aplikacji (z dodatkiem sygnatury czasowej). Może to być zadanie uruchamiane co miesiąc, które obejmuje wszystkich klientów lub tokeny.
  • Dodaj logikę serwera, aby co jakiś czas aktualizować sygnaturę czasową tokena, niezależnie od tego, czy token się zmienił.

Przykład logiki na Androida służącej do aktualizowania tokenów za pomocą WorkManagera znajdziesz w artykule Zarządzanie tokenami Komunikacji w chmurze na blogu Firebase.

Niezależnie od tego, jaki schemat czasowy stosujesz, pamiętaj o okresowej aktualizacji tokenów. Częstotliwość aktualizacji raz w miesiącu zapewnia odpowiednią równowagę między wpływem na baterię a wykrywaniem nieaktywnych tokenów rejestracji. Dzięki temu masz też pewność, że każde urządzenie, które stanie się nieaktywne, będzie mieć odświeżoną rejestrację, gdy znów stanie się aktywne. Odświeżanie częściej 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 rejestracji 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 nieaktualnych tokenów z tematów,

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

  1. Aplikacja powinna ponownie subskrybować tematy raz w miesiącu i za każdym razem, gdy zmieni się token rejestracji. Jest to rozwiązanie samonaprawiające się, w którym subskrypcje pojawiają się automatycznie, gdy aplikacja znów stanie się aktywna.
  2. Jeśli instancja aplikacji jest nieaktywna przez miesiąc (lub w okresie, który określasz jako nieaktywny), powinnaś/powinieneś anulować subskrypcję tematów za pomocą pakietu Firebase Admin SDK, aby usunąć z poziomu backendu FCM mapowanie tokenu na temat.

Dzięki tym 2 krokom rozgałęzienia będą się szybciej odbywać, ponieważ jest mniej nieaktualnych tokenów, do których można się rozgałęzić, a nieaktualne instancje aplikacji automatycznie ponownie się subskrybują, gdy znów będą aktywne.

Pomiar skuteczności przesyłania

Aby uzyskać jak najbardziej dokładny 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, które mają dużą liczbę subskrybentów. Jeśli część z nich jest nieaktywna, wpływ na statystyki dotyczące dostarczania może z czasem wzrosnąć.

Zanim utworzysz kierowanie wiadomości na token, weź pod uwagę te kwestie:

  • Czy Google Analytics, dane przechwycone w BigQuery lub inne sygnały śledzenia wskazują, że token jest aktywny?
  • Czy w ciągu pewnego czasu próby dostarczenia wiadomości regularnie kończyły się niepowodzeniem?
  • Czy token rejestracji został zaktualizowany na Twoich serwerach w ciągu ostatniego miesiąca?
  • Czy w przypadku urządzeń z Androidem interfejs API danych FCM zgłasza wysoki odsetek niepowodzeń przy dostarczaniu wiadomości z powodu droppedDeviceInactive?

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