Setting Up Push Notifications for iOS Apps with Firebase Cloud Messaging (FCM) and Google Cloud Platform (GCP)
Overview
This guide walks through the complete setup for sending push notifications to an iOS app using Firebase Cloud Messaging (FCM), Google Cloud Functions, and other GCP services. We’ll cover the iOS app configuration, backend setup, and architecture.
Architecture Diagram
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ │ │ │ │ │
│ iOS App │◄────┤ Firebase │◄────┤ Google Cloud │
│ (SwiftUI) │ │ Cloud │ │ Functions │
│ │ │ Messaging │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
▲ ▲ ▲
│ │ │
│ │ │
│ │ │
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ │ │ │ │ │
│ Apple Push │ │ Google Cloud │ │ Cloud │
│ Notification │ │ Storage │ │ Scheduler │
│ Service (APNs) │ │ (Firestore) │ │ │
│ │ │ │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
1. iOS App Setup
Prerequisites
- Xcode 14+
- iOS 15+
- Apple Developer Account
- Firebase Account
Step 1: Create iOS Project
// AwayAppsApp.swift
import SwiftUI
import FirebaseCore
import FirebaseMessaging
@main
struct AwayAppsApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Step 2: Configure AppDelegate
class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
FirebaseApp.configure()
UNUserNotificationCenter.current().delegate = self
Messaging.messaging().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
if granted {
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("FCM registration token: \(fcmToken ?? "")")
// Send token to your backend
}
}
Step 3: Add Required Files
- Add
GoogleService-Info.plist
to your project - Configure entitlements for push notifications
- Add required capabilities in Xcode
2. Firebase Setup
Step 1: Create Firebase Project
- Go to Firebase Console
- Create new project
- Add iOS app to project
- Download
GoogleService-Info.plist
Step 2: Configure APNs
- In Firebase Console, go to Project Settings
- Add APNs authentication key from Apple Developer Portal
- Upload the key to Firebase
3. Google Cloud Functions Setup
Step 1: Create Cloud Function
// index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.sendNotification = functions.https.onRequest(async (req, res) => {
try {
const { token, title, body } = req.body;
const message = {
notification: {
title,
body
},
token
};
const response = await admin.messaging().send(message);
res.status(200).send(response);
} catch (error) {
res.status(500).send(error);
}
});
Step 2: Deploy Function
firebase deploy --only functions
4. Cloud Scheduler Setup
Step 1: Create Scheduled Job
- Go to Cloud Scheduler in GCP Console
- Create new job
- Set schedule (e.g.,
0 8 * * *
for 8 AM daily) - Configure HTTP target to call your Cloud Function
5. Testing
Step 1: Get FCM Token
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
print("FCM registration token: \(fcmToken ?? "")")
}
Step 2: Send Test Notification
- Use Firebase Console
- Send test message using FCM token
- Verify receipt on device
Common Issues and Solutions
- “Default app has already been configured”
- Ensure
FirebaseApp.configure()
is called only once - Remove from SwiftUI init if present in AppDelegate
- Ensure
- Missing Info.plist
- Set “Generate Info.plist File” to Yes in Build Settings
- Add custom keys via Info tab
- Push Notifications Not Working in TestFlight
- Ensure
aps-environment
is set toproduction
- Verify APNs key is uploaded to Firebase
- Check device token is current
- Ensure
Best Practices
- Token Management
- Store FCM tokens in your backend
- Update tokens when they refresh
- Remove invalid tokens
- Error Handling
- Implement proper error handling in Cloud Functions
- Log failed notifications
- Implement retry logic
- Testing
- Test on real devices
- Test in different app states (foreground, background, terminated)
- Test with different notification types
Conclusion
This setup provides a robust foundation for sending push notifications to iOS apps. The architecture is scalable and can be extended to support additional features like notification grouping, rich notifications, and analytics.