1. Introduzione
Ultimo aggiornamento: 04/04/2022
Questo codelab ti guida nel processo di sviluppo di un'app multipiattaforma con Firebase Cloud Messaging (FCM) utilizzando Flutter. Scriverai una parte dell'implementazione dell'app, per poi compilarla ed eseguirla senza problemi su tre piattaforme: Android, iOS e web. Scoprirai anche come integrare FCM in Flutter e come scrivere codice per ricevere e inviare messaggi. Infine, il codelab introduce la funzionalità di blocchi specifici della piattaforma dell'API HTTP v1 di FCM, che consente di inviare un messaggio con comportamenti diversi su piattaforme diverse.
Prerequisito
Conoscenza di base di Flutter.
Cosa imparerai a fare
- Come configurare e creare un'app Flutter.
- Come aggiungere le dipendenze FCM.
- Come inviare singoli messaggi FCM alla tua app.
- Come inviare messaggi FCM per argomenti alla tua app.
Che cosa ti serve
- L'ultima versione stabile di Android Studio configurata con i plug-in Dart e Flutter.
Puoi eseguire il codelab utilizzando uno dei seguenti dispositivi:
- Un dispositivo Android fisico collegato al computer.
- Un emulatore Android (vedi Eseguire app sull'emulatore Android).
- Un browser a tua scelta, ad esempio Chrome.
Se vuoi eseguire il codelab utilizzando la piattaforma iOS, hai bisogno di un dispositivo iOS, un account Apple Developer e un dispositivo macOS con Xcode installato.
2. Configurazione di Flutter
Se hai già configurato un ambiente di sviluppo Flutter, salta questa sezione.
Per configurare un ambiente di sviluppo Flutter:
- Scarica e installa Flutter per il tuo sistema operativo: Installazione | Flutter
- Assicurati che lo strumento Flutter sia aggiunto al percorso.
- Configura l'editor per Flutter come mostrato in Configurare un editor | Flutter. Assicurati di installare i plug-in Flutter e Dart per l'editor. Per il resto del codelab, utilizzerai Android Studio.
- Dalla riga di comando, esegui
flutter doctor
, che analizza la configurazione ed elenca le dipendenze mancanti che devono essere corrette. Segui le istruzioni per correggere eventuali dipendenze importanti mancanti. Tieni presente che alcune dipendenze potrebbero non essere necessarie. Ad esempio, se non intendi sviluppare per iOS, una dipendenza CocoaPods mancante non sarà un problema bloccante. - Esegui questo comando per creare l'app Flutter nella directory
fcmflutter
flutter create --org com.flutter.fcm --project-name fcmflutter fcmflutter
, quindi cambia directory infcmflutter
.
- In Android Studio, vai a File -> Apri, trova il percorso dell'app Flutter e poi fai clic su Apri per aprire il progetto in Android Studio. Il codice dell'app si trova nel file
lib/main.dart
.
Nella barra degli strumenti di Android Studio, fai clic sulla Freccia giù per selezionare un dispositivo Android. Se il selettore di destinazione è vuoto, installa dispositivi Android virtuali o il browser Chrome o il simulatore iOS se preferisci avviare l'app da un browser web o da un dispositivo iOS. Potresti dover avviare manualmente il dispositivo e aggiornare l'elenco per trovare il dispositivo di destinazione.
Fai clic su Esegui per avviare l'app.
Complimenti! Hai creato un'app Flutter.
3. Configurazione di Firebase e FlutterFire
Per sviluppare un'app che si integra con Firebase Cloud Messaging utilizzando Flutter, devi:
- Un progetto Firebase.
- Un'interfaccia a riga di comando di Firebase funzionante.
- Un'installazione di FlutterFire.
- Un'app configurata e generata con
flutterfire configure
.
Crea il tuo progetto Firebase
Se hai già un progetto Firebase, puoi saltare questo passaggio.
- Accedi alla console Firebase utilizzando il tuo Account Google.
- Fai clic sul pulsante per creare un nuovo progetto, quindi inserisci un nome per il progetto (ad esempio
fcm4flutter
).
- Fai clic su Continua.
- Se richiesto, leggi e accetta i termini di Firebase, quindi fai clic su Continua.
- (Facoltativo) Attiva l'assistenza AI nella console Firebase (denominata "Gemini in Firebase").
- Per questo codelab non hai bisogno di Google Analytics, quindi disattiva l'opzione Google Analytics.
- Fai clic su Crea progetto, attendi il provisioning del progetto, poi fai clic su Continua.
Complimenti! Hai creato un progetto Firebase.
Configura l'interfaccia a riga di comando di Firebase
Se hai configurato la CLI di Firebase, puoi saltare questo passaggio.
Vai al riferimento per l'interfaccia a riga di comando di Firebase per scaricare e installare l'interfaccia a riga di comando di Firebase. Accedi a Firebase con il tuo Account Google utilizzando il seguente comando:
firebase login
Configurare FlutterFire
- Installa il plug-in FlutterFire utilizzando il comando:
flutter pub add firebase_core
- Installa il plug-in FCM:
flutter pub add firebase_messaging
- Configura l'interfaccia a riga di comando FlutterFire:
dart pub global activate flutterfire_cli
- Configura il progetto Firebase su Flutter:
flutterfire configure --project=fcm4flutter.
utilizza i tasti freccia e la barra spaziatrice per selezionare le piattaforme o premi Invio per utilizzare le piattaforme predefinite.
Questo codelab utilizza le piattaforme predefinite (Android, iOS e web), ma puoi selezionarne solo una o due. Se ti viene richiesto l'ID bundle iOS, inserisci com.flutter.fcm.fcmflutter
o il tuo ID bundle iOS nel formato [company domain name].[project name]
. Al termine del comando, aggiorna la pagina della console Firebase. Vedrai che sono state create app per le piattaforme selezionate nel progetto Firebase.
Questo comando genera un file firebase_options.dart
nella directory lib
, che contiene tutte le opzioni necessarie per l'inizializzazione.
Configurare Cloud Messaging per iOS
- Vai alla pagina sviluppatore Apple e fai clic su Crea una chiave nella scheda Chiavi.
- Inserisci il nome della chiave e seleziona Servizi di notifiche push di Apple (APN).
- Scarica il file della chiave, che ha un'estensione
.p8
. - Nella console Firebase, vai alle Impostazioni progetto del progetto e scegli la scheda Cloud Messaging.
- Carica il file della chiave APN per l'app per iOS nella scheda Cloud Messaging. Inserisci l'ID chiave APNs dalla scheda Cloud Messaging e l'ID team, che puoi trovare nel Member Center (Centro membri) di Apple.
4. Preparazione FCM
Prima che un'app possa ricevere messaggi da FCM, deve:
- Inizializza FlutterFire.
- Richiedi le autorizzazioni alle notifiche.
- Registrati con FCM per ottenere un token di registrazione.
Inizializzazione
Per inizializzare il servizio, sostituisci la funzione principale (lib/main.dart
) con questo codice:
// core Flutter primitives
import 'package:flutter/foundation.dart';
// core FlutterFire dependency
import 'package:firebase_core/firebase_core.dart';
// generated by
flutterfire configure
import 'firebase_options.dart';
// FlutterFire's Firebase Cloud Messaging plugin
import 'package:firebase_messaging/firebase_messaging.dart';
// TODO: Add stream controller
// TODO: Define the background message handler
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
// TODO: Request permission
// TODO: Register with FCM
// TODO: Set up foreground message handler
// TODO: Set up background message handler
runApp(MyApp());
}
Poi esegui Tools -> Flutter -> Flutter Pub Get in Android Studio per caricare i pacchetti aggiunti in Configura FlutterFire e visualizzare il codice con l'impostazione Intellisense appropriata in Android Studio.
In questo modo viene inizializzato FlutterFire per la piattaforma corrente DefaultFirebaseOptions.currentPlatform
, che viene importata dal file firebase_options.dart
generato. Tieni presente che initializeApp
è una funzione asincrona e la parola chiave await
garantisce che l'inizializzazione sia completata prima di eseguire l'applicazione.
Richiedi autorizzazione
L'app deve chiedere all'utente l'autorizzazione per ricevere notifiche. Il metodo requestPermission
fornito da firebase_messaging
mostra una finestra di dialogo o un popup che chiede all'utente di concedere o negare l'autorizzazione.
Innanzitutto, copia questo codice nella funzione principale sotto il commento TODO: Request permission
. Il valore settings
restituito indica se l'utente ha concesso l'autorizzazione. Ti consigliamo di richiedere l'autorizzazione solo quando l'utente deve utilizzare una funzionalità che richiede l'accesso (ad esempio, quando l'utente attiva le notifiche nelle impostazioni dell'app). In questo codelab, per semplicità, richiediamo l'autorizzazione all'avvio dell'app.
final messaging = FirebaseMessaging.instance;
final settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
if (kDebugMode) {
print('Permission granted: ${settings.authorizationStatus}');
}
Successivamente, nella barra degli strumenti di Android Studio, seleziona Chrome (web)
dal selettore di destinazione e poi esegui di nuovo l'app.
Si apre quindi una scheda di Chrome con un popup che chiede l'autorizzazione. Se fai clic su Allow
, nella console di Android Studio viene visualizzato un log: Permission granted: AuthorizationStatus.authorized
. Dopo aver consentito o bloccato la richiesta di autorizzazione, la tua risposta viene memorizzata insieme all'app nel browser e il popup non viene più visualizzato. Tieni presente che quando esegui di nuovo l'app web su Android Studio, potrebbe esserti richiesta di nuovo l'autorizzazione.
Registrazione
Copia questo codice nella funzione principale sotto il commento TODO: Register with FCM
per registrarti a FCM. La chiamata getToken
restituisce un token di registrazione che può essere utilizzato dal server dell'app o dall'ambiente server attendibile per inviare messaggi agli utenti.
// It requests a registration token for sending messages to users from your App server or other trusted server environment.
String? token = await messaging.getToken();
if (kDebugMode) {
print('Registration Token=$token');
}
Nella barra degli strumenti di Android Studio, seleziona un dispositivo Android ed esegui l'app. Nella console di Android Studio, il token di registrazione viene stampato in questo modo:
I/flutter ( 3717): Permission granted: AuthorizationStatus.authorized I/flutter ( 3717): Registration Token=dch. . . D2P:APA9. . .kbb4
Copialo in un editor di testo, perché lo utilizzerai per inviare messaggi in un secondo momento.
uses-sdk:minSdkVersion 16 cannot be smaller than version 19 declared in library [:firebase_messaging]
Passaggi aggiuntivi per ricevere messaggi sul web
Le app web richiedono due passaggi aggiuntivi per ottenere il token di registrazione e rimanere in ascolto dei messaggi in arrivo. Il web deve trasmettere una chiave VAPID a getToken
per autorizzare l'invio di richieste ai servizi di notifica push web supportati.
Innanzitutto, apri la scheda Cloud Messaging del progetto Firebase nella console Firebase, scorri verso il basso fino alla sezione Configurazione web per trovare la coppia di chiavi esistente o generare una nuova coppia di chiavi. Fai clic sul pulsante evidenziato per copiare la chiave in modo che possa essere utilizzata come vapidKey.
Poi, sostituisci il codice di registrazione nella sezione Registrazione con questo codice e aggiorna la chiave VAPID:
// TODO: replace with your own VAPID key
const vapidKey = "<YOUR_PUBLIC_VAPID_KEY_HERE>";
// use the registration token to send messages to users from your trusted server environment
String? token;
if (DefaultFirebaseOptions.currentPlatform == DefaultFirebaseOptions.web) {
token = await messaging.getToken(
vapidKey: vapidKey,
);
} else {
token = await messaging.getToken();
}
if (kDebugMode) {
print('Registration Token=$token');
}
A questo punto, crea un file firebase-messaging-sw.js
sotto la directory web/
nella radice del progetto. Copia il seguente codice in firebase-messaging-sw.js
per consentire all'app web di ricevere eventi onMessage
. Per saperne di più, consulta la sezione Impostazione delle opzioni di notifica nel service worker.
importScripts("https://www.gstatic.com/firebasejs/9.6.10/firebase-app-compat.js");
importScripts("https://www.gstatic.com/firebasejs/9.6.10/firebase-messaging-compat.js");
// todo Copy/paste firebaseConfig from Firebase Console
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
};
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
// todo Set up background message handler
Dopodiché, nella scheda Impostazioni progetto -> Generale, scorri verso il basso e trova App web, copia la sezione di codice firebaseConfig
e incollala in firebase-messaging-sw.js
.
Infine, nella barra degli strumenti di Android Studio, seleziona Chrome (web)
nel selettore di destinazione ed esegui l'app. Nella console di Android Studio, il token di registrazione viene stampato nel seguente modo:
Debug service listening on ws://127.0.0.1:61538/BLQQ3Fg-h7I=/ws Permission granted: AuthorizationStatus.authorized Registration Token=fH. . .ue:APA91. . .qwt3chpv
Copia il token di registrazione in un editor di testo in modo da poterlo utilizzare per inviare messaggi in un secondo momento.
Passaggi aggiuntivi per ricevere messaggi su iOS
Per ricevere messaggi da FCM, i dispositivi iOS devono attivare Notifiche push e Modalità in background su Xcode:
- In Android Studio, fai clic con il tasto destro del mouse sul nome del progetto e seleziona Flutter -> Open iOS module in Xcode (Apri il modulo iOS in Xcode).
- Dopo l'avvio di Xcode, attiva Notifiche push e Modalità in background nella scheda Firma e funzionalità per la destinazione del progetto. Per ulteriori informazioni, consulta Configurare l'app.
- Nella barra degli strumenti di Android Studio, seleziona un dispositivo iOS nel selettore di destinazione ed esegui l'app. Dopo aver concesso l'autorizzazione per le notifiche, il token di registrazione viene stampato nella console di Android Studio.
Congratulazioni, hai registrato correttamente la tua app con FCM. Ora puoi ricevere messaggi, come descritto nella sezione successiva.
5. Ricevere messaggi da FCM
Configurare i gestori di messaggi
L'app deve gestire gli eventi onMessage
quando i messaggi arrivano mentre l'app è in modalità in primo piano e gli eventi onBackgroundMessage
quando l'app è in background.
Gestore dei messaggi in primo piano
Innanzitutto, aggiungi un controller di stream dopo il commento TODO: Add stream controller
nel file main.dart
per passare i messaggi dal gestore di eventi alla UI.
import 'package:rxdart/rxdart.dart';
// used to pass messages from event handler to the UI
final _messageStreamController = BehaviorSubject<RemoteMessage>();
Per aggiungere la dipendenza rxdart, esegui questo comando dalla directory del progetto: flutter pub add rxdart
.
Successivamente, esegui Strumenti -> Flutter -> Flutter Pub Get in Android Studio per caricare il pacchetto rxdart.dart
e visualizzare il codice con le impostazioni Intellisense appropriate in Android Studio.
Quindi, aggiungi un gestore eventi per ascoltare i messaggi in primo piano dopo il commento TODO: Set up foreground message handler
. Stampa i log e pubblica il messaggio nel controller di stream.
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
if (kDebugMode) {
print('Handling a foreground message: ${message.messageId}');
print('Message data: ${message.data}');
print('Message notification: ${message.notification?.title}');
print('Message notification: ${message.notification?.body}');
}
_messageStreamController.sink.add(message);
});
Dopodiché, sostituisci il widget State originale nel file main.dart
con questo codice, che aggiunge un abbonato al controller di stream nel widget State e visualizza l'ultimo messaggio nel widget.
class _MyHomePageState extends State<MyHomePage> {
String _lastMessage = "";
_MyHomePageState() {
_messageStreamController.listen((message) {
setState(() {
if (message.notification != null) {
_lastMessage = 'Received a notification message:'
'\nTitle=${message.notification?.title},'
'\nBody=${message.notification?.body},'
'\nData=${message.data}';
} else {
_lastMessage = 'Received a data message: ${message.data}';
}
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Last message from Firebase Messaging:',
style: Theme.of(context).textTheme.titleLarge),
Text(_lastMessage, style: Theme.of(context).textTheme.bodyLarge),
],
),
),
);
}
}
Gestore di messaggi in background per Android/iOS
I messaggi vengono gestiti dal gestore onBackgroundMessage
mentre l'app è in background. Il gestore deve essere una funzione di primo livello. L'interfaccia utente può essere aggiornata quando l'app viene portata in primo piano gestendo i messaggi (vedi Gestione dell'interazione) o sincronizzandosi con il server dell'app.
Crea la funzione del gestore dopo il commento TODO: Define the background message handler
al di fuori della funzione principale e chiamala nella funzione principale dopo il commento TODO: Set up background message handler
.
// TODO: Define the background message handler
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
if (kDebugMode) {
print("Handling a background message: ${message.messageId}");
print('Message data: ${message.data}');
print('Message notification: ${message.notification?.title}');
print('Message notification: ${message.notification?.body}');
}
}
void main() {
...
// TODO: Set up background message handler
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(MyApp());
}
Gestore dei messaggi in background per il web
A partire dalla versione 11.2.8 di FlutterFire firebase_messaging, la gestione dei messaggi in background sulle piattaforme basate sul web richiede un flusso diverso. Pertanto, devi aggiungere un gestore di messaggi separato nel service worker web/firebase-messaging-sw.js
.
messaging.onBackgroundMessage((message) => {
console.log("onBackgroundMessage", message);
});
Configurare il server dell'app
- Importa il codice del server iniziale aprendo il progetto https://github.com/FirebaseExtended/firebase_fcm_flutter/tree/main/server in Android Studio. Il server è un progetto Java basato su Gradle con una dipendenza dall'SDK firebase-admin, che fornisce la funzionalità di invio dei messaggi FCM.
- Configura un account di servizio Firebase che consenta all'SDK Firebase Admin di autorizzare le chiamate alle API FCM. Apri le Impostazioni progetto nella console Firebase e seleziona la scheda Service account. Scegli "Java" e fai clic su
Generate new private key
per scaricare lo snippet di configurazione. - Rinomina il file in
service-account.json
e copialo nel percorsosrc/main/resources
del progetto del server.
Inviare un messaggio di prova
Nel file FcmSender.java
, sendMessageToFcmRegistrationToken
compone un messaggio di notifica con un payload di dati. Il token di registrazione ha come target l'istanza dell'app a cui viene inviato il messaggio.
private static void sendMessageToFcmRegistrationToken() throws Exception {
String registrationToken = "REPLACE_WITH_FCM_REGISTRATION_TOKEN";
Message message =
Message.builder()
.putData("FCM", "https://firebase.google.com/docs/cloud-messaging")
.putData("flutter", "https://flutter.dev/")
.setNotification(
Notification.builder()
.setTitle("Try this new app")
.setBody("Learn how FCM works with Flutter")
.build())
.setToken(registrationToken)
.build();
FirebaseMessaging.getInstance().send(message);
System.out.println("Message to FCM Registration Token sent successfully!!");
}
- Copia il token di registrazione Android copiato dalla sezione Registrazione e incollalo nel valore della variabile
registrationToken
. - Fai clic su Esegui
per eseguire la funzione principale e inviare il messaggio all'utente tramite FCM.
Quando l'app per Android è in background, il messaggio viene visualizzato nella barra delle notifiche.
Quando l'app per Android è in primo piano, nella console di Android Studio viene visualizzato il log "Handling a foreground message" (Gestione di un messaggio in primo piano). I contenuti del messaggio vengono visualizzati anche nella UI perché è iscritta al controller di flusso per i nuovi messaggi.
Se incolli il token di registrazione e invii il messaggio dal server dell'app o da un altro ambiente server attendibile, vedrai un comportamento simile:
- Quando l'app web è in background (ovvero quando è nascosta da un'altra finestra o è attiva un'altra scheda), viene visualizzata una notifica web.
- Quando l'app web è in primo piano, puoi visualizzare il log nella console Chrome facendo clic con il tasto destro del mouse sul web e selezionando
Inspect
. I contenuti del messaggio vengono visualizzati anche nell'interfaccia utente.
6. Inviare un messaggio all'argomento
La funzionalità di override della piattaforma dell'API FCM HTTP v1 consente a una richiesta di invio di messaggi di avere comportamenti diversi su piattaforme diverse. Un caso d'uso di questa funzionalità è la visualizzazione di contenuti diversi dei messaggi di notifica in base alla piattaforma. La funzionalità viene utilizzata al meglio quando si scelgono come target più dispositivi (che potrebbero coprire più piattaforme) con la messaggistica per argomenti. Questa sezione illustra i passaggi per fare in modo che la tua app riceva un messaggio dell'argomento personalizzato per ogni piattaforma.
Iscrizione a un argomento dal client
Per abbonarti a un argomento, chiama il metodo messaging.subscribeToTopic
alla fine della funzione principale nel file main.dart
dell'app Flutter.
// subscribe to a topic.
const topic = 'app_promotion';
await messaging.subscribeToTopic(topic);
[Facoltativo] Iscriviti a un argomento dal server per il web
Puoi saltare questa sezione se non esegui lo sviluppo sulla piattaforma web.
L'SDK FCM JS attualmente non supporta l'iscrizione agli argomenti lato client. In alternativa, puoi abbonarti utilizzando l'API di gestione degli argomenti lato server dell'SDK Admin. Questo codice illustra la sottoscrizione di argomenti lato server con l'SDK Admin Java.
private static void subscribeFcmRegistrationTokensToTopic() throws Exception {
List<String> registrationTokens =
Arrays.asList(
"REPLACE_WITH_FCM_REGISTRATION_TOKEN"); // TODO: add FCM Registration Tokens to
// subscribe
String topicName = "app_promotion";
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic(registrationTokens, topicName);
System.out.printf("Num tokens successfully subscribed %d", response.getSuccessCount());
}
Apri il server delle app e fai clic su Esegui per eseguire la funzione principale nel file
FcmSubscriptionManager.java
:
Invia un messaggio con override della piattaformaa un argomento
Ora puoi inviare un messaggio di override della piattaforma dell'argomento. Nel seguente snippet di codice:
- Costruisci una richiesta di invio con un messaggio di base e il titolo "
A new app is available
". - Il messaggio genera una notifica di visualizzazione con il titolo "
A new app is available
" su iOS e sulle piattaforme web. - Il messaggio genera una notifica di visualizzazione con il titolo "
A new Android app is available
" sui dispositivi Android.
private static void sendMessageToFcmTopic() throws Exception {
String topicName = "app_promotion";
Message message =
Message.builder()
.setNotification(
Notification.builder()
.setTitle("A new app is available")
.setBody("Check out our latest app in the app store.")
.build())
.setAndroidConfig(
AndroidConfig.builder()
.setNotification(
AndroidNotification.builder()
.setTitle("A new Android app is available")
.setBody("Our latest app is available on Google Play store")
.build())
.build())
.setTopic("app_promotion")
.build();
FirebaseMessaging.getInstance().send(message);
System.out.println("Message to topic sent successfully!!");
}
Nella funzione principale del file FcmSender.java
, rimuovi il commento da sendMessageToFcmTopic();
. Fai clic su Esegui per inviare il messaggio dell'argomento.
7. Riepilogo e passaggi successivi
In sintesi, hai imparato a sviluppare app multipiattaforma coinvolgenti utilizzando Flutter e FCM, il che include la configurazione dell'ambiente, l'integrazione delle dipendenze e la ricezione e l'invio di messaggi. Per approfondire, consulta i seguenti materiali:
Codelab
- Per scoprire di più su come Flutter funziona con altri prodotti Firebase, inclusi l'autenticazione utente e la sincronizzazione dei dati, consulta Scopri Firebase per Flutter.
- Per saperne di più su FCM, inclusi i messaggi in-app e gli argomenti: Utilizzare FCM e FIAM per inviare messaggi agli utenti e Il tuo primo messaggio push multicast utilizzando gli argomenti FCM