As of April 10, 2018, Google has deprecated GCM. The GCM server and client APIs are deprecated and will be removed as soon as April 11, 2019. Migrate GCM apps to Firebase Cloud Messaging (FCM), which inherits the reliable and scalable GCM infrastructure, plus many new features. See the migration guide to learn more.

Migrate a GCM Client App for iOS to Firebase Cloud Messaging

Migrate an existing GCM client app on iOS to Firebase Cloud Messaging (FCM) using the instructions in this guide.

Enabling/disabling method swizzling

Method swizzling available with FCM simplifies your client code. However, for developers who prefer not to use it, FCM allows you to disable method swizzling by adding the FirebaseAppDelegateProxyEnabledflag in the app’s Info.plist file and setting its value to NO (boolean value).

FCM swizzling affects how you handle the default registration token, and how you handle downstream message callbacks. Where applicable, this guide provides migration examples both with and without method swizzling enabled.

Add your GCM project as a Firebase project

  1. In the Firebase console, select Add project.

  2. Select your GCM project from the list of existing Google Cloud projects, and select Add Firebase.

  3. In the Firebase welcome screen, select Add Firebase to your iOS App.

  4. Provide your bundle name and optional App store ID, and select Add App. A new GoogleServices-info.plist file for your Firebase app is downloaded.

  5. Select Continue and follow the detailed instructions for creating an xcworkspace file for your app and connecting to Firebase on startup.

Prerequisites

Make sure your valid APNs certificates are uploaded to the Firebase console.

  1. Select the gear icon next to your project name at top left, and select Project Settings.
  2. Select the Cloud Messaging tab.
  3. Select the Upload Certificate button for your develpment certificate, your production certificate, or both. At least one is required.
  4. For each certificate, select the .p12 file, provide the password if any, and select Save.

Switch to FCM in your Podfile

Before

Google/CloudMessaging

After

Firebase/Messaging

Initializing the service

Previously, the GCM API required client apps to start and configure the GCM service. FCM is initialized as part of overall Firebase app initialization.

Before

  <pre class="prettyprint">[[GGLInstanceID sharedInstance] startWithConfig:[GGLInstanceIDConfig defaultConfig]]

[GCMService sharedInstance] startWithConfig:[GCMConfig defaultConfig]];

After

// No extra messaging code required.
// Configure FCM and other Firebase APIs with a single call.
[FIRApp configure];

Default registration token

You must follow different steps to migrate registration token-related code depending on whether or not you disable swizzling. By default, FCM swizzles the AppDelegate methods to:

  • get the APNs token and associate it with the registration token automatically. The FCM SDK swizzles the AppDelegate’s remote notification handlers to get the APNs token for the device.

  • automatically report notification related analytics, such "notification opened" and "notifcation foregrounded." These analytics are available if the message is sent from Firebase Notifications.

Generating the token with swizzling enabled

Before

NSDictionary *instanceIDOptions = @{
    kGGLInstanceIDRegisterAPNSOption : appDelegate.apnsDeviceToken,
    kGGLInstanceIDAPNSServerTypeSandboxOption : @([self isSandboxApp]),
};
[[GGLInstanceID sharedInstance]
    tokenWithAuthorizedEntity:[AppDelegate appGCMSenderID]
                        scope:kGGLInstanceIDScopeGCM
                      options:instanceIDOptions
                      handler:^(NSString *token, NSError *error){
    // handle token or error.
}];

After

// Get the default token
// The first time you call this, the token may not be available, in which case
// the SDK returns nil.
// Once the token is fetched from the server, the SDK posts a token refresh
// notification that you can listen for in order to access the new token.

NSString *token = [[FIRInstanceID instanceID] token];

Generating the token with swizzling disabled

Before

NSDictionary *instanceIDOptions = @{
    kGGLInstanceIDRegisterAPNSOption : appDelegate.apnsDeviceToken,
    kGGLInstanceIDAPNSServerTypeSandboxOption : @([self isSandboxApp]),
};
[[GGLInstanceID sharedInstance]
    tokenWithAuthorizedEntity:[AppDelegate appGCMSenderID]
                        scope:kGGLInstanceIDScopeGCM
                      options:instanceIDOptions
                      handler:^(NSString *token, NSError *error){
    // handle token or error.
}];

After

// With "FirebaseAppDelegateProxyEnabled": NO

- (void)application:(UIApplication *)application
    didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  [[FIRMessaging messaging] setAPNSToken:deviceToken
                                    type:FIRMessagingAPNSTokenTypeProd];
}

Token Refresh

FCM does not require the GGLInstanceIDDelegate protocol for token refresh. Instead, the SDK posts the notification kFIRInstanceIDTokenRefreshNotification to let the app know when the token is refreshed. The token refresh notification is invoked whenever the SDK generates a token, including the first time.

Before

@implementation AppDelegate : NSObject 
GGLInstanceIDConfig *config = [GGLInstanceIDConfig defaultConfig];
config.delegate = self;
[[GGLInstanceID sharedInstance] startWithConfig:config];

//#pragma - GGLInstanceIDDelegate protocol
- (void)onTokenRefresh() {
  // get all new tokens, resubscribe to topics etc.
}
@end

After

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    ...

      // Add observer to listen for the token refresh notification.
      [[NSNotificationCenter defaultCenter]
       addObserver:self selector:@selector(onTokenRefresh)
              name:FIRMessagingRegistrationTokenRefreshedNotification object:nil];

            ...

          }

- (void)onTokenRefresh {
  // Get the default token if the earlier default token was nil. If the we already
  // had a default token most likely this will be nil too. But that is OK we just
  // wait for another notification of this type.
  NSString *token = [[FIRInstanceID instanceID] token];
  // custom stuff as before.
}

Downstream send callbacks

In FCM, swizzling relieves your client app of the need to call appDidReceiveMessage for message handling. If you disable swizzling, the API closely resembles GCM’s, only with updated FIRMessaging naming.

Handling downstream callbacks with swizzling enabled

Before

- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
          fetchCompletionHandler:
              (void (^)(UIBackgroundFetchResult))completionHandler {
  // Let GCM know about the message for analytics etc.
  [GCMService appDidReceiveMessage:userInfo];
  // handle your message.
}

After

- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
          fetchCompletionHandler:
              (void (^)(UIBackgroundFetchResult))completionHandler {
  // Handle your message. With swizzling enabled, no need to indicate
  // that a message was received.
}

Handling downstream callbacks with swizzling disabled

Before

- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
          fetchCompletionHandler:
              (void (^)(UIBackgroundFetchResult))completionHandler {
  // Let GCM know about the message for analytics etc.
  [GCMService appDidReceiveMessage:userInfo];
  // handle your message.
}

After

- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo
          fetchCompletionHandler:
              (void (^)(UIBackgroundFetchResult))completionHandler {
  // Let FCM know about the message for analytics etc.
  [[FIRMessaging messaging] appDidReceiveMessage:userInfo];
  // handle your message.
}

Upstream send callbacks

To receive status updates for upstream sends, GCM apps must implement the GCMReceiverDelegate protocol and implement its methods. With FCM, client apps listen for the relevant notifications by adding observers for each of them.

Before

@implementation AppDelegate : NSObject 
GCMConfig *config = [GCMConfig defaultConfig];
config.delegate = self;
[[GCMConfig sharedInstance] startWithConfig:config];

// GCMReceiverDelegate protocol methods

- (void)willSendDataMessageWithID:(NSString *)messageID error:(NSError *)error;
  // check if any error while sending message
}

- (void)didSendDataMessageWithID:(NSString *)messageID {
  // successfully sent upstream message with id ‘messageID`
}

- (void)didDeleteMessagesOnServer {
  // some messages were deleted(TTL expired) on the server, lets’ retrieve them.
}

@end

After

[[NSNotificationCenter defaultCenter]
     addObserver:self selector:@selector(sendDataMessageFailure:)
            name:FIRMessagingSendErrorNotification object:nil];

[[NSNotificationCenter defaultCenter]
     addObserver:self selector:@selector(sendDataMessageSuccess:)
            name:FIRMessagingSendSuccessNotification object:nil];

[[NSNotificationCenter defaultCenter]
     addObserver:self selector:@selector(didDeleteMessagesOnServer)
            name:FIRMessagingMessagesDeletedNotification object:nil];

// contains error info
- (void)sendDataMessageFailure:(NSNotification *)notification {
  NSString *messageID = (NSString *)message.object;
}
- (void)sendDataMessageSuccess:(NSNotification *)notification {
  NSString *messageID = (NSString *)message.object;
  NSDictionary *userInfo = message.userInfo;
}

- (void)didDeleteMessagesOnServer {
}

Update server endpoints

Update your server code to use new FCM endpoints for sending messages via HTTP and XMPP. Note that the new FCM version of gcm-http.googleapis.com/gcm/ is fcm.googleapis.com/fcm/ (without "http"):

GCM endpoint FCM endpoint
gcm-http.googleapis.com/gcm/ fcm.googleapis.com/fcm/
gcm-xmpp.googleapis.com fcm-xmpp.googleapis.com

FCM supports HTTP and XMPP protocols that are virtually identical to the GCM server protocols, so you don't need to update your sending logic for the migration. Optionally, you may want to evaluate the FCM HTTP v1 API, which offers an improved security model and new capabilities for customizing messages across platforms.

フィードバックを送信...