Jeśli używasz interfejsów API FCM do programowego tworzenia żądań wysyłania, możesz zauważyć, że z czasem marnujesz zasoby, wysyłając wiadomości na nieaktywne urządzenia z nieaktualnymi rejestracjami. Ta sytuacja może wpłynąć na dane o dostarczaniu wiadomości raportowane w konsoli Firebase lub dane eksportowane do BigQuery, co może się objawiać jako gwałtowny (ale nieprawdziwy) spadek współczynników dostarczania. 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 biegiem czasu prawdopodobieństwo, że urządzenie ponownie połączy się z FCM, maleje. Wysyłanie wiadomości i rozsyłanie do 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 jest powiązana 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 ją. Gdy rejestracja wygaśnie, FCM oznacza ją jako nieprawidłową i odrzuca wysyłanie do niej. Pamiętaj, że identyfikatorami instalacji Firebase (FID) zarządza usługa instalacji Firebase (FIS), a nie FCM. W rzadkich przypadkach, gdy urządzenie ponownie się połączy, a aplikacja zostanie otwarta po usunięciu jej rejestracji, aplikacja kliencka ponownie zarejestruje się w FCM za pomocą FID pobranego z FIS. Pamiętaj, że FID może się zmienić. Więcej informacji o tym, kiedy FID są ponownie wydawane, znajdziesz w artykule Zarządzanie instalacjami Firebase.
W przypadku innych platform, takich jak iOS, FCM korzysta z podstawowej usługi push (np. APNs), która nie ma takiego samego 270-dniowego okresu wygaśnięcia opartego na braku aktywności . Zalecamy proaktywne utrzymywanie aktualności rejestracji i usuwanie nieaktualnych rejestracji.
Podstawowe sprawdzone metody
W każdej aplikacji, która używa FCM interfejsów API do programowego tworzenia żądań wysyłania, należy stosować się do kilku podstawowych zasad. Główne sprawdzone metody to:
- Pobieranie identyfikatorów instalacji Firebase (FID) z FCM i przechowywanie ich na serwerze aplikacji. Ważną rolą serwera jest śledzenie zarejestrowanego FID każdego klienta i utrzymywanie aktualnej listy aktywnych FID. Zdecydowanie zalecamy zaimplementowanie w bazie danych sygnatury czasowej rejestracji i aktualizowanie jej za każdym razem, gdy rejestracja jest przesyłana.
- Utrzymywanie aktualności rejestracji i usuwanie nieaktualnych rejestracji. 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 pozwolą Ci to osiągnąć.
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 kierowanych z interfejsu API lub użyć do subskrypcji tematów.
Zdecydowanie zalecamy zapisywanie FID na serwerze aplikacji wraz z sygnaturą czasową za każdym razem, gdy jest on przesyłany. Dzięki aktualizowaniu sygnatury czasowej przy każdym żądaniu przesłania Twój serwer wie, kiedy instancja aplikacji została ostatnio otwarta i pomyślnie zsynchronizowana z backendem FCM.
W zależności od tego, czy automatyczna inicjalizacja jest włączona czy wyłączona (w tym nieobsługiwana), rejestrację i aktualizacje należy obsługiwać w ten sposób:
- (Zalecane) Gdy automatyczna inicjalizacja jest włączona: pakiet SDK automatycznie utrzymuje aktualność rejestracji i monitoruje zmiany. Wywołanie zwrotne
onRegistered()jest regularnie wywoływane podczas rutynowych synchronizacji przy uruchamianiu aplikacji, a także w przypadku zmian FID. Wystarczy zaimplementować to wywołanie zwrotne, aby przesłać FID na serwer i zapisać bieżącą sygnaturę czasową. - Gdy automatyczna inicjalizacja jest wyłączona: Wywołanie zwrotne
onRegistered()nie zostanie automatycznie wywołane na początku. Aby śledzić rejestracje i utrzymywać ich aktualność, wywołajregister()przy uruchamianiu aplikacji, np. w Androidzie w `onCreate()` głównego działania.onCreate(). Pomyślne wywołanie uruchamia proces rejestracjiFCM za pomocą FID i dostarcza go doonRegistered()wywołania zwrotnego, co umożliwia aplikacji przesłanie FID i zaktualizowanie sygnatury czasowej na serwerze.
Przykład: przechowywanie FID i sygnatur czasowych w Cloud Firestore
Możesz na przykład użyć Cloud Firestore do przechowywania FID w kolekcji o nazwie
fcmRegistrations. Każdy identyfikator dokumentu w kolekcji odpowiada identyfikatorowi użytkownika, a dokument przechowuje bieżący FID i sygnaturę czasową jego ostatniej aktualizacji. Użyj funkcji set tak jak w tym przykładzie w Kotlinie:
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)
}
Za każdym razem, gdy identyfikator instalacji Firebase zostanie pomyślnie zarejestrowany lub zaktualizowany, wywoływane jest wywołanie zwrotne
onRegistered(). Należy zaimplementować to wywołanie zwrotne, aby przesłać 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
register()
przy uruchamianiu aplikacji (np. w onCreate()), aby uruchomić proces rejestracji i dostarczenie FID
za pomocą
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)
}
}
Utrzymywanie aktualności rejestracji i usuwanie nieaktualnych rejestracji
Określenie, czy rejestracja jest aktualna czy nieaktualna, nie zawsze jest proste. Aby uwzględnić wszystkie przypadki, musisz przyjąć 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 musisz samodzielnie określić kryteria, które Ci odpowiadają.
Wykrywanie nieprawidłowych odpowiedzi z backendu FCM
Pamiętaj, aby wykrywać nieprawidłowe odpowiedzi z FCM i reagować na nie, usuwając z 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 wysyłania było kierowane do nieprawidłowych lub wygasłych rejestracji:
UNREGISTERED(HTTP 404)INVALID_ARGUMENT(HTTP 400)
Jeśli masz pewność, że ładunek wiadomości jest prawidłowy, a w przypadku kierowanej rejestracji otrzymujesz jedną z tych odpowiedzi, możesz bezpiecznie usunąć rekord tej rejestracji, ponieważ nigdy nie będzie ona już prawidłowa. Aby na przykład usunąć nieprawidłowe rejestracje z Cloud Firestore, możesz wdrożyć i uruchomić funkcję taką jak ta:
// 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 braku aktywności lub jeśli klient wyraźnie się wyrejestrował. Jeśli chcesz dokładniej śledzić brak aktualizacji zgodnie z własnymi definicjami, możesz proaktywnie usuwać nieaktualne rejestracje.
Regularne aktualizowanie rejestracji
Niezależnie od tego, czy rejestracje są oparte na FID, czy na starszych tokenach rejestracji, serwer powinien zawsze aktualizować sygnaturę czasową rejestracji w bazie danych przy każdym żądaniu przesłania. Ta sygnatura czasowa służy jako sygnał dla instalacji aplikacji, informując, że klient pomyślnie otworzył aplikację i zsynchronizował się z FCM backendem. W zależności od używanych interfejsów API zaimplementuj odpowiednią strategię:
Interfejsy API identyfikatora instalacji Firebase (zalecane)
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 zajmuje się odświeżaniem w ramach automatycznej inicjalizacji, regularnie
dostarczając prawidłowy bieżący FID do wywołania zwrotnego
onRegistered()
podczas rutynowych synchronizacji przy uruchamianiu aplikacji.
Aby serwer był aktualny, zaimplementuj strategie przesyłania przy uruchamianiu opisane w sekcji Pobieranie i przechowywanie identyfikatorów instalacji Firebase :
- Automatyczna inicjalizacja włączona: pakiet SDK automatycznie dba o to, aby najnowszy FID był wysyłany na serwer podczas rutynowych synchronizacji przy uruchamianiu aplikacji.
- Automatyczna inicjalizacja wyłączona lub nieobsługiwana: wywołaj
register()przy uruchamianiu aplikacji (np. w Androidzie w `onCreate()` głównego działania), aby wymusić sekwencję rejestracji i wywołać dostarczenie FID do wywołania zwrotnegoonRegistered().onCreate()
Te strategie gwarantują, że serwer zawsze będzie mieć najnowszy aktywny FID i będzie mógł automatycznie odzyskać dane po nieudanych przesłaniach, co sprawi, że aplikacja będzie bardzo odporna.
Wycofane interfejsy API tokenów 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. Wymaga to:
- Dodania logiki aplikacji w aplikacji klienckiej, aby pobrać bieżący token za pomocą
odpowiedniego wywołania interfejsu API (np.
token(completion):w przypadku platform Apple lubgetToken()w przypadku Androida), a następnie wysł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. - Dodania logiki serwera, aby aktualizować sygnaturę czasową tokena w regularnych odstępach czasu, niezależnie od tego, czy token się zmienił.
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, aby okresowo aktualizować tokeny. Częstotliwość aktualizacji raz na miesiąc zapewnia dobry kompromis 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 swoją 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, upewnij się, że sygnatura czasowa rejestracji urządzenia mieści się w okresie nieaktualności. Możesz na przykład zaimplementować
Cloud Functions for Firebase aby codziennie sprawdzać, czy
sygnatura czasowa mieści się w zdefiniowanym okresie braku aktualizacji, 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(); });
});
Anulowanie subskrypcji tematów w przypadku nieaktualnych rejestracji
Jeśli używasz tematów, możesz też anulować subskrypcję tematów w przypadku nieaktualnych rejestracji. Wymaga to wykonania 2 czynności:
- Aplikacja powinna ponownie subskrybować tematy za każdym razem, gdy zmieni się identyfikator instalacji Firebase (FID). Dzięki temu subskrypcje pojawią się automatycznie, gdy aplikacja ponownie stanie się aktywna.
- Jeśli instancja aplikacji jest nieaktywna przez miesiąc (lub przez zdefiniowany przez Ciebie okres nieaktualności), powinna anulować subskrypcję tematów za pomocą pakietu Firebase Admin SDK aby usunąć mapowanie identyfikatora instalacji Firebase na temat z FCM backendu.
Dzięki tym 2 czynnościom rozsyłanie będzie szybsze, ponieważ będzie mniej nieaktualnych rejestracji, do których trzeba rozsyłać wiadomości, a nieaktualne instancje aplikacji automatycznie ponownie zasubskrybują tematy, gdy ponownie staną się aktywne.
Mierzenie skuteczności dostarczania
Aby uzyskać jak 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 do tematów z dużą liczbą subskrybentów. Jeśli część tych subskrybentów jest nieaktywna, wpływ na statystyki dostarczania może być z czasem znaczący.
Zanim zaczniesz kierować wiadomości do instancji aplikacji, zastanów się:
- 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ę przez dłuższy czas?
- Czy identyfikator instalacji Firebase został zaktualizowany na Twoich serwerach w ciągu ostatniego miesiąca?
- 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 Omówienie dostarczania wiadomości.