Setup Push Notifications with Firebase in Xamarin Forms for iOS

Use Google Firebase in iOS Xamarin Forms project to send and receive push notifications. Lately i covered the aspect on setting up the Push notification on Xamarin Forms for Android in Firebase.

Let’s now cover the same on iOS.

Register the app in Google Firebase

In my experience dealing directly with the APNS (Apple push notifications service) it’s a little bit tricky because you have to deal yourself with the maintaining of the devices tokens (cleaning and modifying), and to send a broadcast message you have to send by yourself all the requests to all the device tokens you registered.

To get over of this situation you can use the Firebase service by Google to let it to deal with this problems.

Let’s start.

  • Go to console.firebase.google.com/ and click on Add Project
  • insert the name of the app
  • set default Locality and accept the privacy and conditions

Inside the panel of the panel of the app click now on the iOS icon to add the iOS app

  • add the bundle identifier of the app in ID bundle iOS
  • click on Register App
  • download the GoogleService-Info.plist file
  • in Visual Studio add it to the .iOS project, right click on the file and set it Build Action > BundleResource
  • return to the wizard click ok to all

Now return to the panel of the app in Firebase

  • on the main page of Firebase click again on the iOS icon and click on the gear icon (settings)
  • go to Cloud Messaging
  • you have now to upload the Authentication Key for APN, it’s a certificate from Apple that allow the Firebase server to connect to the APN (Apple Push Notification) server

Go to the Apple certificate portal developer.apple.com/account/ios/certificate

  • click on Keys > All and click on + (add)
  • give it a name (for example “firebase”) and enable Apple Push Notifications service (APNs) and confirm
  • download the key in .p8 format and click done

Now return to the last seen Firebase screen

  • go to the Authentication Key for APN form
  • you have to insert the Key id (go to the keys in the Apple Certificate portal, click on the generated key and copy Key ID), and the Team ID (can be found in developer.apple.com/account/#/membership in Team ID row)

Ok. Done.

And now some code

Now return in Visual Studio add this Nuget Xamarin.Firebase.iOS.CloudMessaging.

Add this code in the AppDelegate class

The code is quite self explanatory and it setup the Firebase service in iOS, register a single device token you can use, and register also a channel (like the same in Android, topics are channels of communications in order to send global push notifications to all the devices that listen to a channel), the default topic is all (on topics).

namespace MyApp
{
    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
                                                      , IUNUserNotificationCenterDelegate
                                                      , IMessagingDelegate
    {
        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App());

            if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
            {
                // iOS 10
                var authOptions = UNAuthorizationOptions.Alert | UNAuthorizationOptions.Badge | UNAuthorizationOptions.Sound;
                UNUserNotificationCenter.Current.RequestAuthorization(authOptions, (granted, error) =>
                {
                    Console.WriteLine(granted);
                });

                // For iOS 10 display notification (sent via APNS)
                UNUserNotificationCenter.Current.Delegate = this;
            }
            else
            {
                // iOS 9 <=
                var allNotificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
                var settings = UIUserNotificationSettings.GetSettingsForTypes(allNotificationTypes, null);
                UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
            }

            UIApplication.SharedApplication.RegisterForRemoteNotifications();

            Firebase.Core.App.Configure();

            Firebase.InstanceID.InstanceId.Notifications.ObserveTokenRefresh((sender, e) => {
                var newToken = Firebase.InstanceID.InstanceId.SharedInstance.Token;
                // if you want to send notification per user, use this token
                System.Diagnostics.Debug.WriteLine(newToken);

                Messaging.SharedInstance.Connect((error) =>
                {
                    if (error == null)
                    {
                        Messaging.SharedInstance.Subscribe("/topics/all");
                    }
                    System.Diagnostics.Debug.WriteLine(error != null ? "error occured" : "connect success");
                });
            });

            return base.FinishedLaunching(app, options);
        }

        public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
        {
            PushNotificationManager.DidRegisterRemoteNotifications(deviceToken);
        }

        public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
        {
            PushNotificationManager.RemoteNotificationRegistrationFailed(error);

        }
        // To receive notifications in foregroung on iOS 9 and below.
        // To receive notifications in background in any iOS version
        public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
        {
            PushNotificationManager.DidReceiveMessage(userInfo);
        }

        public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
        {
            NSString title = ((userInfo["aps"] as NSDictionary)["alert"] as NSDictionary)["title"] as NSString;
            NSString message = ((userInfo["aps"] as NSDictionary)["alert"] as NSDictionary)["body"] as NSString;

            // optionally you can send a Xamarin Forms message to 
            // inform the Xamarin Forms Application to handle the notification
            //MessagingCenter.Send(new MessageNotificationReceived()
            //{
            //    Title = title,
            //    Message = message,
            //}, "");
        }
    }
}

And you are done!