Setting Up Firebase Cloud Messaging (FCM) in a Flutter iOS App (with Appwrite Integration)
No fluff. Here’s how to get push notifications working in your Flutter iOS app, with messages coming either straight from Firebase or through Appwrite. Covers foreground, background, and terminated state delivery. Works for both development and production. Assume you know how to edit a Flutter project and use Xcode.
1. Firebase Console: Add iOS App
- Go to Firebase Console, create a project (or use an existing one).
- Add your iOS app:
- Use your app’s bundle ID (must match
ios/Runner
).
- Use your app’s bundle ID (must match
- Download the generated
GoogleService-Info.plist
. - Put
GoogleService-Info.plist
inios/Runner/
and add it to the Xcode Runner target (“Copy if needed”).
2. Configure APNs in Firebase
You have two choices; pick one.
Option A: APNs Auth Key (Recommended)
- In Apple Developer:
- Create an APNs Auth Key.
- Download the
.p8
file, note the Key ID and Team ID.
- In Firebase Console > Project Settings > Cloud Messaging, upload the
.p8
key and fill in Key ID/Team ID.
Option B: APNs Certificates (Obsolete, but still possible)
- In Apple Developer, create/download .p12 certificates for Development and Production.
- Upload both to Firebase in the same place.
- Don’t do this unless forced; use the key.
3. Xcode Project Configuration
- Open your Flutter iOS project:
open ios/Runner.xcworkspace
- In Xcode, Runner target > Signing & Capabilities:
- Add Push Notifications capability.
- Add Background Modes; check Remote notifications.
- Use correct provisioning profile. Debug builds use sandbox APNs, Release/TestFlight use production.
4. Add Firebase Messaging to Flutter
In
pubspec.yaml
:dependencies: firebase_core: any firebase_messaging: any
Run
flutter pub get
.In
main.dart
:import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async { await Firebase.initializeApp(); // Handle background message } void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); runApp(MyApp()); }
5. Request Notification Permission (iOS)
Somewhere early (on app launch):
NotificationSettings settings = await FirebaseMessaging.instance.requestPermission( alert: true, badge: true, sound: true, );
If
settings.authorizationStatus
is authorized or provisional, you can proceed.
6. Get Device FCM Token
After getting permission:
String? fcmToken = await FirebaseMessaging.instance.getToken(); print("FCM Token: $fcmToken");
This is what you need to send notifications.
Listen for token refresh (FCM tokens rotate):
FirebaseMessaging.instance.onTokenRefresh.listen((newToken) { // update your backend/Appwrite with newToken });
7. Handle Notifications in All App States
Foreground
- Messages don’t display natively in foreground. Handle like this:
FirebaseMessaging.onMessage.listen((RemoteMessage message) { // Show your own in-app alert, badge, etc. });
Background/Terminated
Define the background handler as above.
Also, handle notification taps:
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { // Handle notification tap (from background) }); // At app startup, get initial message if app was launched by notification RemoteMessage? initialMsg = await FirebaseMessaging.instance.getInitialMessage(); if (initialMsg != null) { // Handle launch via notification }
8. Appwrite Setup: Add FCM Provider
- In Appwrite Console > Messaging > Providers, add new provider:
- Choose “Push notification”, then “Firebase Cloud Messaging (FCM)”.
- Download service account JSON from Firebase Console > Project Settings > Service Accounts > “Generate new private key”.
- Upload JSON to Appwrite provider config.
- Enable provider.
9. Register Device Token with Appwrite
After login, register the FCM token as a push target for the user:
import 'package:appwrite/appwrite.dart'; Client client = Client() .setEndpoint('https://<YOUR_APPWRITE_ENDPOINT>/v1') .setProject('<YOUR_PROJECT_ID>'); // Set JWT if you use it for authentication Account account = Account(client); String? fcmToken = await FirebaseMessaging.instance.getToken(); if (fcmToken != null) { await account.createPushTarget( targetId: ID.unique(), identifier: fcmToken, // providerId: '<YOUR_FCM_PROVIDER_ID>', // Optional, if multiple ); }
10. Send Notification via Appwrite Dashboard
- Go to Messaging > Messages > Create Message.
- Choose Push notification.
- Fill title, body, data, etc.
- Select your device/user as target.
- Click “Send now”.
11. Testing Notes
- Push won’t work in iOS Simulator. Use real device.
- Debug builds use APNs sandbox; TestFlight/Release use production.
- If using APNs Auth Key, you don’t have to care – it handles both.
- Foreground: notification doesn’t show unless you display it yourself.
- Background: system displays notification, tap triggers
onMessageOpenedApp
. - Terminated: tap triggers
getInitialMessage
. - If not working: check Xcode console, Appwrite logs, Firebase logs, check permissions.
That’s it. You now have push notifications in Flutter iOS, using Firebase, with optional Appwrite as your notification backend. No magic, just steps.