Jeśli do programowego tworzenia żądań wysyłania używasz FCM interfejsów API, możesz zauważyć, że z czasem marnujesz zasoby, wysyłając wiadomości na nieaktywne urządzenia z nieaktualnymi tokenami rejestracji. 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. Z tego przewodnika dowiesz się, jakie działania 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 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 tokenów prawdopodobnie nigdy nie zostanie zrealizowane.
Token może stać się nieaktualny z kilku powodów. Na przykład urządzenie, z którym jest powiązany token, może zostać zgubione, zniszczone lub odłożone i zapomniane.
W przypadku Androida, gdy nieaktualne tokeny osiągną 270 dni nieaktywności, FCM uznaje je za wygasłe. Gdy token wygaśnie, FCM oznaczy go jako nieprawidłowy i odrzuci wysyłanie do niego. W rzadkich przypadkach, gdy urządzenie ponownie się połączy i aplikacja zostanie otwarta, FCM wyda nowy token dla instancji aplikacji.
W przypadku innych platform, takich jak iOS, FCM korzysta z podstawowej usługi push (np. APNs), która nie ma takiego samego 270-dniowego wygaśnięcia tokena na podstawie nieaktywności. Dlatego zalecamy proaktywne utrzymywanie aktualności tokena i usuwanie nieaktualnych tokenów 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 tokenów rejestracji z FCM i przechowywanie ich na serwerze. Ważną rolą serwera jest śledzenie tokena każdego klienta i utrzymywanie aktualnej listy aktywnych tokenów. Zdecydowanie zalecamy zaimplementowanie w kodzie i na serwerach sygnatury czasowej tokena oraz regularne aktualizowanie tej sygnatury.
- Utrzymywanie aktualności tokena i usuwanie nieaktualnych tokenów. Oprócz usuwania tokenów, które FCM nie uważa już za prawidłowe, możesz chcieć monitorować inne oznaki, że tokeny stały się nieaktualne, i usuwać je proaktywnie. Z tego przewodnika dowiesz się, jak to zrobić.
Pobieranie i przechowywanie tokenów rejestracji
Przy pierwszym uruchomieniu aplikacji pakiet SDK FCM generuje token rejestracji dla instancji aplikacji klienta. Jest to token, który musisz uwzględnić w kierowanych żądaniach wysyłania z interfejsu API lub dodać do subskrypcji tematów, aby kierować reklamy na tematy.
Zdecydowanie zalecamy, aby aplikacja pobierała ten token przy pierwszym uruchomieniu i zapisywała go na serwerze aplikacji wraz z sygnaturą czasową. Ta sygnatura czasowa musi być zaimplementowana w kodzie i na serwerach, ponieważ nie jest udostępniana przez FCM pakiety SDK.
Ważne jest też, aby zapisać token na serwerze i zaktualizować 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 wyczyści dane aplikacji;
- aplikacja ponownie stanie się aktywna po wygaśnięciu dotychczasowego 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ą jego ostatniej aktualizacji. Użyj funkcji set zgodnie z tym przykładem w języku Kotlin:
/**
* 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 zostanie pobrany, jest on przechowywany w Cloud Firestore przez wywołanie
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 aktualności tokena i usuwanie nieaktualnych tokenów
Określenie, czy token jest aktualny, czy nieaktualny, nie zawsze jest proste. Aby uwzględnić wszystkie przypadki, musisz przyjąć próg, po przekroczeniu którego tokeny będą uznawane za nieaktualne. Domyślnie FCM uznaje token za nieaktualny, jeśli jego instancja aplikacji nie łączyła się przez miesiąc. Każdy token starszy niż miesiąc prawdopodobnie należy do nieaktywnego urządzenia. Aktywne urządzenie odświeżyłoby swój token.
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 odpowiedzi z nieprawidłowym tokenem z backendu FCM
Pamiętaj, aby wykrywać odpowiedzi z nieprawidłowym tokenem z FCM i reagować na nie, usuwając z systemu wszystkie tokeny rejestracji, 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 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 kierowanego tokena otrzymujesz jedną z tych odpowiedzi, możesz bezpiecznie usunąć rekord tego tokena, ponieważ nigdy nie będzie on już prawidłowy. 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 (error.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 odpowiedź z nieprawidłowym tokenem, jeśli token urządzenia z Androidem wygasł po 270 dniach nieaktywności lub jeśli klient wyraźnie się wyrejestrował. 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. W tym celu musisz:
- Dodać w aplikacji klienta logikę aplikacji, 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. - Dodać logikę serwera, aby regularnie aktualizować sygnaturę czasową tokena, niezależnie od tego, czy token się zmienił, czy nie.
Przykład logiki Androida do aktualizowania tokenów za pomocą WorkManagera, znajdziesz na blogu Firebase w artykule Zarządzanie tokenami Komunikacji w chmurze.
Niezależnie od tego, jakiego wzorca czasowego używasz, pamiętaj o okresowym aktualizowaniu tokenów. 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 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 nieaktualności. Możesz na przykład zaimplementować Cloud Functions for Firebase aby codziennie sprawdzać, czy sygnatura czasowa mieści się w zdefiniowanym 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ż anulować subskrypcję nieaktualnych tokenów w tematach, które subskrybują. Wymaga to wykonania 2 czynności:
- Aplikacja powinna ponownie subskrybować tematy raz w miesiącu i za każdym razem, gdy zmieni się token rejestracji. Tworzy to rozwiązanie samonaprawiające się, w którym subskrypcje pojawiają się automatycznie, gdy aplikacja ponownie stanie się aktywna.
- Jeśli instancja aplikacji jest nieaktywna przez miesiąc (lub Twój własny okres nieaktualności), powinna anulować subskrypcję tematów za pomocą pakietu Firebase Admin SDK aby usunąć mapowanie tokena na temat z backendu FCM.
Dzięki tym 2 krokom zwielokrotnienie wyjściowe będzie szybsze, ponieważ będzie mniej nieaktualnych tokenów, 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, z czasem może to mieć znaczący wpływ na statystyki dostarczania.
Zanim zaczniesz kierować wiadomości na token, zastanów się:
- 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ę przez dłuższy czas?
- Czy token rejestracji 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.