[Guide] GCM Push Notification Integration in iOS App with Working Source Codes

0
3424
google cloud server

Are you working on Google cloud messaging service integration in iOS app? This article is for you! Recently I was working on one iOS app development project where I had to integrate GCM push notification in the app. During integration, I found Google official guide very helpful but It is bit complex.  To ease your task, I tried to compile the step-by-step information specific to GCM messaging services for iOS app with working source code. I am sure it will save your lot of time.  Here we go…

Developed by Google, Google Cloud Messaging, popularly known as GCM, is a mobile service through which third-party application developers are able to send information or notification data to various applications from developer-run servers targeting the Google Android OS as well as extensions or applications developed for the internet browser Google Chrome. Check out complete step by step guide to integrate GCM push notification service in iOS app with working code.

google cloud server

Steps to Integrate GCM in iOS application:

  • Step 1 – Create a project that you target to implement
  • Step 2 – Installation of Pod by following the below steps:
    • Step 2.1 – Open terminal and reach to the main project folder by going to – > cd PATH OF FOLDER
    • Step 2.2 – Run POD init – By running the POD init command, locate the podfile in the project folder
    • Step 2.3 – Open the POD file from the project folder and you will see the following text:
    # Uncomment this line to define a global platform for your project
    # platform :ios, '8.0'
    # Uncomment this line if you're using Swift
    # use_frameworks!
    target 'GoogleCloudMessage' do
    HERE // replace with POD ‘Google/CloudMessaging’
    End
    
    • Step 2.4 – Replace the POD ‘Google/CloudMessaging’ with HERE.
    • Step 2.5 – Save the POD file and return back to the terminal window. Run POD install.
    • Step 2.6 – After all the processes finish, go back to the project folder and open the project with .xcworkspace.

After downloading the configuration file just drag and drop this plist file in to your project.

Appdelegrate.h file:

#import <UIKit/UIKit>;
#import <Google/CloudMessaging>;
@interface AppDelegate : UIResponder <UIApplicationDelegate , GGLInstanceIDDelegate, GCMReceiverDelegate>
@property (strong, nonatomic) UIWindow *window;
@property(nonatomic, readonly, strong) NSString *registrationKey;
@property(nonatomic, readonly, strong) NSString *messageKey;
@property(nonatomic, readonly, strong) NSString *gcmSenderID;
@property(nonatomic, readonly, strong) NSDictionary *registrationOptions;
@end

Appdelegrate.m file:

#import <UIKit/UIKit>;
#import "AppDelegate.h"
@interface AppDelegate ()
@property(nonatomic, strong) void (^registrationHandler)
(NSString *registrationToken, NSError *error);
@property(nonatomic, assign) BOOL connectedToGCM;
@property(nonatomic, strong) NSString* registrationToken;
@property(nonatomic, assign) BOOL subscribedToTopic;
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    
    _registrationKey = @"onRegistrationCompleted";
    _messageKey = @"onMessageReceived";
    
    // Configure the Google context: parses the GoogleService-Info.plist, and initializes
    // the services that have entries in the file
    
    NSError* configureError;
    [[GGLContext sharedInstance] configureWithError:&configureError];
    NSAssert(!configureError, @"Error configuring Google services: %@", configureError);
    _gcmSenderID = [[[GGLContext sharedInstance] configuration] gcmSenderID];
    
    UIUserNotificationType allNotificationTypes =
    (UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge);
    UIUserNotificationSettings *settings =
    [UIUserNotificationSettings settingsForTypes:allNotificationTypes categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
    [[UIApplication sharedApplication] registerForRemoteNotifications];
    
    
    GCMConfig *gcmConfig = [GCMConfig defaultConfig];
    gcmConfig.receiverDelegate = self;
    [[GCMService sharedInstance] startWithConfig:gcmConfig];
    
    __weak typeof(self) weakSelf = self;
    // Handler for registration token request
    _registrationHandler = ^(NSString *registrationToken, NSError *error){
        if (registrationToken != nil) {
            weakSelf.registrationToken = registrationToken;
            NSLog(@"Registration Token: %@", registrationToken);
           // [weakSelf subscribeToTopic];
            NSDictionary *userInfo = @{@"registrationToken":registrationToken};
            [[NSNotificationCenter defaultCenter] postNotificationName:weakSelf.registrationKey
                                                                object:nil
                                                              userInfo:userInfo];
        } else {
            NSLog(@"Registration to GCM failed with error: %@", error.localizedDescription);
            NSDictionary *userInfo = @{@"error":error.localizedDescription};
            [[NSNotificationCenter defaultCenter] postNotificationName:weakSelf.registrationKey
                                                                object:nil
                                                              userInfo:userInfo];
        }
    };


    return YES;
}

Once you configured and initialized the services that has entries in the file GoogleService-Info.plist then create a config and set a delegate that implements the GGLInstaceIDDelegate protocol at the didRegisterForRemoteNotificationsWithDeviceToken method using following code.

- (void)application:(UIApplication *)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
       // Create a config and set a delegate that implements the GGLInstaceIDDelegate protocol.
    
    GGLInstanceIDConfig *instanceIDConfig = [GGLInstanceIDConfig defaultConfig];
    instanceIDConfig.delegate = self;
    
    // Start the GGLInstanceID shared instance with the that config and request a registration
    // token to enable reception of notifications
    
    [[GGLInstanceID sharedInstance] startWithConfig:instanceIDConfig];
    _registrationOptions = @{kGGLInstanceIDRegisterAPNSOption:deviceToken,
                             kGGLInstanceIDAPNSServerTypeSandboxOption:@YES};
    [[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:_gcmSenderID
                                                        scope:kGGLInstanceIDScopeGCM
                                                      options:_registrationOptions
                                                      handler:_registrationHandler];
    
}

- (void)onTokenRefresh {
    // A rotation of the registration tokens is happening, so the app needs to request a new token.
    NSLog(@"The GCM registration token needs to be changed.");
    [[GGLInstanceID sharedInstance] tokenWithAuthorizedEntity:_gcmSenderID
                                                        scope:kGGLInstanceIDScopeGCM
                                                      options:_registrationOptions
                                                      handler:_registrationHandler];
}

- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))handler {
    NSLog(@"Notification received: %@", userInfo);
    // This works only if the app started the GCM service
    [[GCMService sharedInstance] appDidReceiveMessage:userInfo];

    [[NSNotificationCenter defaultCenter] postNotificationName:_messageKey
                                                        object:nil
                                                      userInfo:userInfo];
    handler(UIBackgroundFetchResultNoData);
    
}

- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
    NSLog(@"Notification received: %@", userInfo);
    // This works only if the app started the GCM service
    [[GCMService sharedInstance] appDidReceiveMessage:userInfo];
    // Handle the received message
    
    [[NSNotificationCenter defaultCenter] postNotificationName:_messageKey
                                                        object:nil
                                                      userInfo:userInfo];
    
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Connect to the GCM server to receive non-APNS notifications
    [[GCMService sharedInstance] connectWithHandler:^(NSError *error) {
        if (error) {
            NSLog(@"Could not connect to GCM: %@", error.localizedDescription);
        } else {
            _connectedToGCM = true;
            NSLog(@"Connected to GCM");
        
        }
    }];
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [[GCMService sharedInstance] disconnect];
    
    _connectedToGCM = NO;
    
}

- (void)application:(UIApplication *)application
didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    NSLog(@"Registration for remote notification failed with error: %@", error.localizedDescription);
   
    NSDictionary *userInfo = @{@"error" :error.localizedDescription};
    [[NSNotificationCenter defaultCenter] postNotificationName:_registrationKey
                                                        object:nil
                                                      userInfo:userInfo];
}

I have used all the methods to setup and configure GCM Services which is required and we developed code for Connection, Get Device Registration key and other all required steps in our Appdelegate class. Now use below source code to send upstream messages from one device to another device. This code should be written in your view-controller class “.m” file where you requires to send the push notification on particular event call.

#import "ViewController.h"
#import <Google/CloudMessaging.h>
@interface ViewController ()
@property (strong, nonatomic) IBOutlet UIButton *btnSend;
- (IBAction)send:(id)sender;

@end

@implementation ViewController

- (void)viewDidLoad {
    
    GCMConfig *gcmConfig = [GCMConfig defaultConfig];
    gcmConfig.receiverDelegate = self;
    [[GCMService sharedInstance] startWithConfig:gcmConfig];
    self.messagesSent = 1;
    [super viewDidLoad];
    
}

- (IBAction)send:(id)sender {
    
    NSString *sendUrl = @"https://android.googleapis.com/gcm/send";
    NSString *Registration_Token = @"f8DCxy2Uypc:APA91bF__LdDhDH1Fgz-4ow7LPubvxxxxxxx-qdPF0szKGfmgn_Lfb0GKjAp_xddLxF9UTiI9UjjMlMe3dB284uze4H9yp3sYz0Ol--xxxxxx";// this is the registration token of resever user that we get from our backend like we did with device token usially with ios environment
    
    NSString *title = @"Nitin";
    NSString *body = @"Test";
    
    NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:sendUrl ]];
    req.HTTPMethod = @"POST";
    [req setValue:@"application/json" forHTTPHeaderField: @"Content-Type"];
    [req setValue:@"key=AIzaSyD8XuoWWRT3xxxxxxx" forHTTPHeaderField: @"Authorization"];
    NSDictionary *message = [self getMessageTo:Registration_Token withTitle:title withBody:body];
    NSError *jsonError;
    NSMutableString *jsonString;
    
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:message options:NSJSONWritingPrettyPrinted error:&jsonError];
    if (! jsonData) {
        NSLog(@"Got an error: %@", jsonError);
    } else {
        jsonString = [[NSMutableString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
    
    NSLog(@"json string%@", jsonString);
    
    req.HTTPBody = jsonData;
    [NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
     {
         if (error != nil) {
             NSLog(@"truc error %@",error);
         } else {
             NSLog(@"Success! Response from the GCM server:");
             NSLog(@"%@",response);
         }
     }];
    
    
}
-(NSDictionary *) getMessageTo:(NSString *) to withTitle:(NSString *)   title withBody:(NSString *) body{
  
    NSDictionary *message = @{
                              @"notification" : @{@"title" : title,@"text" : body},
                              @"to" : to
                              };
    return message;
    
}

Now following two methods are a delegate of GCMConfig that will be called when you send the push-notification. Now the following delegate method  will be called and you got to know the status of notification which sent successfully or not.

-(void)willSendDataMessageWithID:(NSString *)messageID error:(NSError *)error {
    if (error) {
        
        NSLog(@"===%@",error.localizedDescription);
    } else {
          NSLog(@"=== Will send message, you can save the messageID to track the message");
    }
}

- (void)didSendDataMessageWithID:(NSString *)messageID {
    
     NSLog(@"=== Did successfully send message identified by messageID");
    //
}

downstream & up stream messagingOnce the app is connected, you are just ready to receive downstream messages and also can send upstream messages. Other options are also available with Google Cloud Messaging Services including topic messaging, reference information and device group messaging. These are available for server APIs and client API.

If you are working on same functionality and finding any query or errors, do write here by comments and I will be there to answer your query. Over to you!