Sprawdzone metody zarządzania rejestracją w FCM

Jeśli do automatycznego tworzenia żądań wysyłania używasz interfejsów FCM API, 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 dotyczące wyświetlania wiadomości raportowane w Firebase konsoli lub dane eksportowane do BigQuery, powodując gwałtowny (ale nieprawdziwy) spadek współczynników wyświetlania. W tym przewodniku omawiamy niektóre środki, 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 FCM od ponad miesiąca. Z czasem prawdopodobieństwo ponownego połączenia urządzenia z FCM maleje. Wysyłanie wiadomości i rozsyłanie do subskrybentów tematów w przypadku tych nieaktualnych rejestracji prawdopodobnie nigdy nie zostanie zrealizowane.

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 schowka i zapomniane.

W przypadku Androida, gdy rejestracja jest nieaktywna przez 270 dni, FCMuznaje 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 połączy się z siecią, 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 są one 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 utrzymywanie aktualności rejestracji i usuwanie nieaktualnych rejestracji.

Podstawowe sprawdzone metody

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

  • Pobierz identyfikatory instalacji Firebase (FID) z FCM i zapisz je na serwerze aplikacji. Ważną rolą serwera jest śledzenie zarejestrowanego identyfikatora 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 z dostępnych opcji.

Pobieranie i przechowywanie identyfikatorów instalacji Firebase

Przy pierwszym uruchomieniu aplikacji pakiet SDK FCM rejestruje instancję aplikacji w 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 zaimplementować 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ć je w aktualności, wywołuj funkcję register() przy uruchamianiu aplikacji, np. na Androidzie w metodzie onCreate() głównej aktywności. Pomyślne wywołanie uruchamia proces FCM rejestracji za pomocą identyfikatora FID i przekazuje go do funkcji zwrotnej onRegistered(), co umożliwia aplikacji przesłanie identyfikatora FID i zaktualizowanie sygnatury czasowej na serwerze.

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

Możesz na przykład użyć Cloud Firestore do przechowywania identyfikatorów 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ływane jest wywołanie zwrotne onRegistered(). Zaimplementuj ten wywołanie zwrotne, aby przesłać identyfikator FID i zaktualizować sygnaturę czasową:

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 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 nieaktualna, nie zawsze jest proste. Aby uwzględnić wszystkie przypadki, należy przyjąć próg, po przekroczeniu którego rejestracje są 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ć za krótki lub za długi, więc 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ć brak aktualizacji 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żdym żądaniu przesłania. Ten sygnatura czasowa służy jako sygnał instalacji aplikacji, informujący 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 API FID nie musisz planować okresowych zadań w tle w aplikacji klienckiej, aby pobierać lub odświeżać rejestracje. Pakiet SDK automatycznie odświeża identyfikator FID w ramach automatycznej inicjalizacji, regularnie przekazując prawidłowy bieżący identyfikator FID do wywołania zwrotnego 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 podczas rutynowych synchronizacji przy uruchamianiu aplikacji na serwer wysyłany był najnowszy identyfikator FID.
  • 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ę 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 do serwera 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 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 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 ponownie stanie się 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, sprawdź, czy sygnatura czasowa rejestracji urządzenia mieści się w okresie nieaktualnoś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ć nieaktualne rejestracje w tematach, do których są one subskrybowane. Obejmuje to 2 etapy:

  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 znowu stanie się aktywna.
  2. Jeśli instancja aplikacji jest nieaktywna przez miesiąc (lub inny okres nieaktywności), należy ją wyrejestrować z tematów za pomocą pakietu SDK Firebase Admin, aby usunąć z FCM backendu mapowanie identyfikatora instalacji Firebase na temat.

Zaletą tych dwóch kroków jest to, że rozsyłanie będzie szybsze, ponieważ będzie mniej nieaktualnych rejestracji, do których trzeba rozsyłać wiadomości. Nieaktualne instancje aplikacji automatycznie ponownie zasubskrybują powiadomienia, gdy znów będą aktywne.

Pomiar 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 zakończyły się niepowodzeniem w określonym czasie?
  • Czy w ciągu ostatniego miesiąca identyfikator instalacji Firebase został zaktualizowany na Twoich serwerach?
  • Czy interfejs FCM Data API na urządzeniach z Androidem zgłasza wysoki odsetek nieudanych dostaw wiadomości z powodu droppedDeviceInactive?

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