Sprawdzone metody zarządzania rejestracją w FCM

Jeśli do tworzenia żądań wysyłania używasz interfejsów API FCM, z czasem możesz zauważyć, że marnujesz zasoby, wysyłając wiadomości na nieaktywne urządzenia z nieaktualnymi rejestracjami. Może to wpłynąć na dane o dostarczaniu wiadomości zgłaszane w Firebasekonsoli lub dane eksportowane do BigQuery, powodując gwałtowny (ale w rzeczywistości nieprawidłowy) spadek współczynników dostarczania. W tym przewodniku znajdziesz informacje o działaniach, które możesz podjąć, aby zapewnić skuteczne kierowanie wiadomości i prawidłowe raportowanie dostarczania.

Nieaktualne i wygasłe rejestracje

Nieaktualne rejestracje są 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 rejestracji i rozsyłane do tematów prawdopodobnie nigdy nie zostaną dostarczone.

Rejestracja może stać się nieaktualna z kilku powodów. Na przykład urządzenie, z którym powiązana jest rejestracja, może zostać zgubione, zniszczone lub odłożone do przechowywania i zapomniane.

W przypadku Androida, gdy rejestracja jest nieaktywna przez 270 dni, FCM uznaje ją za wygasłą i usuwa. Gdy rejestracja wygaśnie, FCM oznaczy ją jako nieprawidłową i odrzuci wysyłanie do niej wiadomości. Pamiętaj, że identyfikatory instalacji Firebase (FID) są zarządzane przez usługę instalacji Firebase (FIS), a nie przez FCM. W rzadkich przypadkach, gdy urządzenie ponownie się połączy, a aplikacja zostanie otwarta po usunięciu rejestracji, aplikacja kliencka ponownie zarejestruje się w FCM, używając identyfikatora FID pobranego z FIS. Pamiętaj, że identyfikator instalacji Firebase może się zmienić. Więcej informacji o tym, kiedy identyfikatory instalacji Firebase są ponownie wydawane, znajdziesz w artykule Zarządzanie instalacjami Firebase.

W przypadku innych platform, takich jak iOS, FCM korzysta z usługi push (np. APNs), która nie ma takiego samego 270-dniowego okresu ważności opartego na braku aktywności. Zalecamy proaktywne dbanie o aktualność rejestracji i usuwanie nieaktualnych rejestracji.

Podstawowe sprawdzone metody

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

  • Pobierz identyfikatory instalacji Firebase (FID)FCM i zapisz je na serwerze aplikacji. Ważną rolą serwera jest śledzenie zarejestrowanych identyfikatorów FID każdego klienta i prowadzenie aktualizowanej listy aktywnych identyfikatorów FID. Zdecydowanie zalecamy wdrożenie w bazie danych znacznika czasu rejestracji i aktualizowanie go za każdym razem, gdy przesyłana jest rejestracja.
  • Dbać o aktualność rejestracji i usuwać nieaktualne rejestracje. Oprócz usuwania rejestracji, które FCM nie uważa już za prawidłowe, możesz monitorować inne oznaki, że rejestracje stały się nieaktualne, i usuwać je proaktywnie. W tym przewodniku omawiamy niektóre opcje, które możesz wykorzystać w tym celu.

Pobieranie i przechowywanie identyfikatorów instalacji Firebase

Przy pierwszym uruchomieniu aplikacji pakiet SDK FCM rejestruje instancję aplikacji w usłudze FCM i zwraca identyfikator instalacji Firebase (FID). Jest to identyfikator, który musisz uwzględnić w żądaniach wysyłania kierowanego z interfejsu API lub użyć w przypadku subskrypcji tematów.

Zdecydowanie zalecamy zapisywanie identyfikatora FID na serwerze aplikacji wraz z sygnaturą czasową za każdym razem, gdy jest on przesyłany. Aktualizując sygnaturę czasową w każdym żądaniu przesyłania, serwer wie, kiedy instancja aplikacji została ostatnio otwarta i pomyślnie zsynchronizowana z FCMbackendem.

W zależności od tego, czy automatyczna inicjalizacja jest włączona czy wyłączona (w tym czy nie jest obsługiwana), rejestrację i aktualizacje należy obsługiwać w ten sposób:

  • (Zalecane) Gdy automatyczna inicjalizacja jest włączona: pakiet SDK automatycznie odświeża rejestrację i monitoruje zmiany. Wywołanie zwrotne onRegistered() jest regularnie wywoływane podczas rutynowych synchronizacji przy uruchamianiu aplikacji, a także w przypadku zmian identyfikatora FID. Wystarczy wdrożyć ten wywołanie zwrotne, aby przesłać identyfikator FID na serwer i zapisać bieżący sygnaturę czasową.
  • Gdy automatyczna inicjalizacja jest wyłączona: wywołanie zwrotne onRegistered() nie będzie automatycznie wywoływane na początku. Aby śledzić rejestracje i utrzymywać ich aktualność, wywołuj funkcję register() przy uruchamianiu aplikacji, np. na Androidzie w głównym działaniu onCreate(). Po udanym połączeniu wywoływany jest proces FCM rejestracji z użyciem identyfikatora FID, który jest przekazywany do funkcji zwrotnej onRegistered() aplikacji. Dzięki temu aplikacja może przesłać identyfikator FID i zaktualizować sygnaturę czasową na serwerze.

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

Możesz na przykład użyć Cloud Firestore, aby przechowywać identyfikatory FID w kolekcji o nazwie fcmRegistrations. Każdy identyfikator dokumentu w kolekcji odpowiada identyfikatorowi użytkownika, a dokument przechowuje bieżący identyfikator FID i sygnaturę czasową ostatniej aktualizacji. Użyj funkcji set w sposób pokazany w tym przykładzie w języku Kotlin:

private fun sendRegistrationToServer(installationId: String?) {
    // If you're running your own server, call API to send registration details and today's date for the user

    // Example shown uses Firestore
    // Add FID and timestamp to Firestore for this user
    val deviceFid = hashMapOf(
        "installationId" to installationId,
        "timestamp" to FieldValue.serverTimestamp(),
    )
    // Get user ID from Firebase Auth or your own server
    Firebase.firestore.collection("fcmRegistrations").document("myuserid")
        .set(deviceFid)
}

Gdy identyfikator instalacji Firebase zostanie zarejestrowany lub zaktualizowany, wywoływana jest funkcja zwrotna onRegistered(). Aby przesłać identyfikator FID i zaktualizować sygnaturę czasową, musisz wdrożyć to wywołanie zwrotne:

override fun onRegistered(installationId: String) {
    Log.d(TAG, "Registered installation ID: $installationId")

    // Send the Firebase Installation ID (FID) to your app server. Your app
    // server should save the FID and update the timestamp upon receipt.
    sendRegistrationToServer(installationId)
}

W przypadku instancji, w których automatyczna inicjalizacja jest wyłączona, wywołaj funkcję register() przy uruchamianiu aplikacji (np. w funkcji onCreate()), aby wywołać proces rejestracji i przesłać identyfikator FID za pomocą funkcji onRegistered():

// Trigger manual registration if auto-initialization is turned off.
FirebaseMessaging.getInstance().register()
    .addOnCompleteListener(this) { task ->
        if (task.isSuccessful) {
            // The registration callback onRegistered() will be invoked with the current FID.
        } else {
            Log.w(TAG, "Failed to register with Firebase Cloud Messaging", task.exception)
        }
    }

Dbanie o aktualność rejestracji i usuwanie nieaktualnych rejestracji

Określenie, czy rejestracja jest aktualna, czy nie, nie zawsze jest proste. Aby uwzględnić wszystkie przypadki, ustal próg, po przekroczeniu którego rejestracje będą uznawane za nieaktualne. Domyślnie FCM uznaje rejestrację za nieaktualną, jeśli instancja aplikacji nie łączyła się przez miesiąc. Każda rejestracja starsza niż miesiąc prawdopodobnie dotyczy nieaktywnego urządzenia. Aktywne urządzenie odświeżyłoby rejestrację.

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ą.

Wykrywanie nieprawidłowych odpowiedzi z backendu FCM

Wykrywaj nieprawidłowe odpowiedzi z FCM i usuwaj ze swojego systemu wszystkie rejestracje, które są nieprawidłowe lub wygasły. W przypadku interfejsu HTTP v1 API te komunikaty o błędach mogą wskazywać, że żądanie wysłania było kierowane na nieprawidłowe lub wygasłe rejestracje:

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

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

        // Firebase Installation ID comes from the client FCM SDKs
        const firebaseInstallationId = 'YOUR_FIREBASE_INSTALLATION_ID';

        const message = {
            data: {
                // Information you want to send inside of notification
            },
            fid: firebaseInstallationId
        };

        // Send message to device with provided Firebase Installation ID
        getMessaging().send(message)
        .then((response) => {
            // Response is a message ID string.
        })
        .catch((error) => {
            // Delete registration for user if error code is UNREGISTERED or INVALID_ARGUMENT.
            if (error.errorCode == "messaging/registration-token-not-registered") {
                // If you're running your own server, call API to delete the registration for the user
                // Example shown uses Firestore
                // Get user ID from Firebase Auth or your own server
                Firebase.firestore.collection("fcmRegistrations").document(user.uid).delete()
            }
        });

FCM zwraca nieprawidłową odpowiedź, jeśli rejestracja urządzenia z Androidem wygasła po 270 dniach nieaktywności lub jeśli klient wyraźnie wyrejestrował urządzenie. Jeśli chcesz dokładniej śledzić nieaktualność zgodnie z własnymi definicjami, możesz proaktywnie usuwać nieaktualne rejestracje.

Regularnie aktualizuj rejestracje

Niezależnie od tego, czy rejestracje są oparte na identyfikatorach FID, czy na starszych tokenach rejestracji, serwer powinien zawsze aktualizować sygnaturę czasową rejestracji w bazie danych przy każdej prośbie o przesłanie. Ten sygnatura czasowa służy jako sygnał instalacji aplikacji, informując klienta, że aplikacja została otwarta i zsynchronizowana z backendem FCM. W zależności od używanych interfejsów API wdróż odpowiednią strategię:

W przypadku aplikacji klienckich korzystających z interfejsów FID API nie musisz planować okresowych zadań w tle w aplikacji klienckiej, aby pobierać lub odświeżać rejestracje. W przypadku automatycznej inicjalizacji pakiet SDK automatycznie odświeża identyfikator FID, regularnie przekazując prawidłowy bieżący identyfikator FID do funkcji zwrotnej onRegistered() podczas rutynowych synchronizacji przy uruchamianiu aplikacji.

Aby serwer był aktualny, wdróż strategie przesyłania podczas uruchamiania opisane w artykule Pobieranie i przechowywanie identyfikatorów instalacji Firebase:

  • Automatyczna inicjalizacja włączona: pakiet SDK automatycznie dba o to, aby najnowszy identyfikator FID był wysyłany na serwer podczas rutynowych synchronizacji przy uruchamianiu aplikacji.
  • Automatyczna inicjalizacja jest wyłączona lub nie jest obsługiwana: wywołaj register() przy uruchamianiu aplikacji (np. na Androidzie w głównej aktywności onCreate()), aby wymusić sekwencję rejestracji i wywołać dostarczenie identyfikatora FID do funkcji zwrotnej onRegistered().

Te strategie gwarantują, że serwer zawsze ma najnowszy aktywny identyfikator FID i może automatycznie odzyskiwać dane po nieudanych przesłaniach, co sprawia, że aplikacja jest wysoce odporna na awarie.

Wycofane interfejsy API tokena rejestracji

Jeśli używasz starszych tokenów rejestracji, pakiet SDK klienta nie zarządza automatycznie odświeżaniem podczas rutynowych synchronizacji. Dlatego zalecamy okresowe pobieranie i aktualizowanie wszystkich tokenów rejestracji na serwerze. Wymagania:

  • Dodaj do aplikacji klienta logikę, która będzie pobierać 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 wysyłać bieżący token na serwer aplikacji w celu przechowywania (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 starszych tokenów za pomocą WorkManagera znajdziesz w artykule Managing Cloud Messaging Tokens 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 stanowi dobrą równowagę między wpływem na baterię a wykrywaniem nieaktywnych tokenów rejestracji. Dzięki temu odświeżaniu 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 rejestracji

Zanim wyślesz wiadomości na urządzenie, upewnij się, że sygnatura czasowa rejestracji urządzenia mieści się w okresie ważności. Możesz na przykład wdrożyć 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 rejestracje:

exports.pruneRegistrations = functions.pubsub.schedule('every 24 hours').onRun(async (context) => {
  // Get all documents where the timestamp exceeds is not within the past month
  const staleRegistrationsResult = await admin.firestore().collection('fcmRegistrations')
      .where("timestamp", "<", Date.now() - EXPIRATION_TIME)
      .get();
  // Delete devices with stale registrations
  staleRegistrationsResult.forEach(function(doc) { doc.ref.delete(); });
});
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 nieaktywnych rejestracji tematów

Jeśli używasz tematów, możesz też anulować subskrypcję nieaktualnych rejestracji w tematach, które subskrybują. Obejmuje to 2 kroki:

  1. Aplikacja powinna ponownie subskrybować tematy za każdym razem, gdy zmieni się identyfikator instalacji Firebase (FID). Dzięki temu subskrypcje będą automatycznie pojawiać się ponownie, gdy aplikacja znów stanie się aktywna.
  2. Jeśli instancja aplikacji jest nieaktywna przez miesiąc (lub przez okres nieaktywności określony przez Ciebie), należy anulować jej subskrypcję tematów za pomocą pakietu SDK Firebase Admin, aby usunąć z FCM backendu mapowanie identyfikatora instalacji Firebase na temat.

Zaletą tych 2 kroków jest to, że rozsyłanie nastąpi szybciej, ponieważ będzie mniej nieaktualnych rejestracji, do których trzeba wysłać rozsyłanie. Nieaktualne instancje aplikacji automatycznie ponownie zasubskrybują, 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 instancję aplikacji, weź pod uwagę te kwestie:

  • Czy Google Analytics, dane zarejestrowane w BigQuery lub inne sygnały śledzenia wskazują, że rejestracja jest aktywna?
  • Czy poprzednie próby dostarczenia nie powiodły się w sposób ciągły w określonym czasie?
  • Czy w ciągu ostatniego miesiąca identyfikator instalacji Firebase 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 wiadomości znajdziesz w artykule Dostarczanie wiadomości.