Cómo implementar notificaciones push en Xamarin iOS

Imagen de TeroVesalainen en Pixabay 
Si has iniciado el desarrollo de una aplicación móvil, casi con total seguridad uno de los principales requerimientos será la necesidad de recibir notificaciones push, en las siguientes lineas veremos paso a paso como poner en pie la recepción de notificaciones remotas en dispositivos iOS.

Configuración, generación y obtención del certificado

Lo primero que vamos a necesitar es la creación de un certificado de "Push Notifications" para nuestra aplicación, para ello tendremos que acceder al área de miembros de Apple Developer. Una vez que hayamos accedido al área, tendremos que pulsar sobre la opción "Certificates, IDs & Profiles":



Partiendo de la base que ya hemos creado el identificador para nuestra aplicación, lo siguiente que tenemos que hacer es editar los datos de configuración del AppID:


Una vez dentro de los datos de edición de nuestro AppID, buscamos la opción de "Push Notifications", verificamos que la tenemos marcada y pulsamos sobre el botón "Configure":


En la siguiente pantalla, tendremos que elegir según las necesidades del momento entre un certificado para entorno de desarrollo o producción (dirigido a aplicaciones publicadas en la Apple Store).


Seguidamente tendremos que seleccionar el fichero CSR, previamente generado siguiendo los pasos que se indican en la ayuda oficial de Apple Developer. Personalmente lo tengo siempre guardado en el escritorio del Mac, porque podemos usar el mismo fichero para la generación y obtención de otros certificados, esto es a gusto del consumidor.



Una vez seleccionado nuestro fichero CSR, pulsamos en continuar y obtendremos un resultado similar a la siguiente pantalla:


Tan solo nos queda pulsar sobre el botón "Download", pulsar sobre el archivo una vez descargado y se instalará de forma automática en nuestro llavero del Mac, como vemos a continuación:


Llegados a este momento ya tendríamos finalizada la labor de "burocracia" que necesitamos para enviar y recibir notificaciones push remotas en nuestro dispositivo iOS.

Caducidad de los certificados

Como nota de interés es importante destacar que tanto el certificado de desarrollo como el de producción tienen una fecha de caducidad, así que decidle a Siri que os lo recuerde para su renovación, el proceso para la renovación es el mismo que hemos visto anteriormente, solo tendremos que repetir los pasos y listo.

Particularidades en Xamarin iOS

Hasta ahora no hemos visto nada específico que afecte solo a Xamarin, de hecho los pasos mencionados anteriormente podrían ser llevados a cabo para una aplicación nativa iOS realizada en XCode, así que ahora vamos a ver las particularidades y ajustes a realizar en nuestro código para poder recibir notificaciones push.

Habilitar las notificaciones remotas en segundo plano

Para habilitar las notificaciones remotas en segundo plano tendremos que abrir el fichero Info.plist que se encuentra en la raiz de nuestro proyecto iOS, pulsar sobre la pestaña "Funcionalidad", "Modos en segundo plano", marcar la casilla "Habilitar modos en segundo plano" y por último "Notificaciones remotas", os debería quedar así:


Modificar AppDelegate para habilitar notificaciones

Ahora tenemos que localizar el archivo AppDelegate que se encuentra en el raiz del proyecto iOS y agregar el siguiente código:

        public override bool FinishedLaunching(UIApplication app, NSDictionary options)
        {
            settingsForRemoteNotifications();

            global::Xamarin.Forms.Forms.Init();
            LoadApplication(new App());

            return base.FinishedLaunching(app, options);
        }

        private void settingsForRemoteNotifications()
        {
                UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
                UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
        }


El código anterior permite mostrar al usuario la confirmación para habilitar o no la recepción de notificaciones remotas.

Captura de notificaciones en primero y segundo plano

Para capturar los eventos de recepción de notificaciones cuando nuestra aplicación se encuentra en primer plano tenemos que sobreescribir el método "DidReceiveRemoteNotification", para capturar la recepción cuando la aplicación se encuentra en segundo plano sobreescribimos el método "ReceivedRemoteNotification", esto lo hacemos dentro de la clase AppDelegate de nuestro proyecto iOS, debería de quedar algo así.

        public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
        {
            this.receivedPushNotification(userInfo, application);
        }

        public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
        {
            this.receivedPushNotification(userInfo, application);
        }

        private void receivedPushNotification(NSDictionary userInfo, UIApplication application)
        {
            if (application.ApplicationState == UIApplicationState.Active)
            {
                return;
            }

            var aps = userInfo.ObjectForKey(new NSString("aps")) as NSDictionary;
            if (aps != null)
            {
                string message = aps.ObjectForKey(new NSString("alert")) as NSString;
                var parameters = aps.ObjectForKey(new NSString("parameters")) as NSDictionary;

                NSError error;
                var json = NSJsonSerialization.Serialize(parameters, NSJsonWritingOptions.PrettyPrinted, out error);
                Newtonsoft.Json.Linq.JObject jObject = Newtonsoft.Json.Linq.JObject.Parse(json.ToString(NSStringEncoding.UTF8));

                Notification _notification = new Notification()
                {
                    Message = message,
                    Parameters = jObject
                };

                crossApp.OnPushNotification(_notification);
            }
        }


La llamada "crossApp.OnPushNotification", justo al final del bloque de código, hace referencia a un método que deberemos incluir en nuestro proyecto común de Xamarin Forms, este será ya el encargado de mostrar la interfaz adecuada para cada tipo de notificación.

Obtención del token del dispositivo

Para la obtención del token del dispositivo tendremos que agregar el siguiente código también a la clase AppDelegate del proyecto iOS:

        public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
        {
            byte[] dt = deviceToken.ToArray();
            string token = BitConverter.ToString(dt).Replace("-", "").ToUpperInvariant();

            // TODO: Save device token and register on backend (server)
        }

¿Que es eso del token?, es el identificador del registro de nuestro dispositivo en el APN de Apple, es único y es el que nos permitirá enviar de forma personalizada las notificaciones a nuestro dispositivo móvil. Lo guardaremos a buen recaudo porque posteriormente nos servirá para el envío.

Este sería un buen momento para guardar en el backend el deviceToken obtenido, de manera que ya en el servidor tuviésemos a buen recaudo el identificador del dispositivo para enviar las notificaciones. 

Hasta ahora tenemos toda la maquinaria preparada en la parte cliente de nuestra aplicación, pero nos quedaría por "cocinar" el componente backend que será el encargado de realizar el envío de las notificaciones, así que vamos a verlo en detalle.

Exportar certificado Apple Push Service a formato p12

Para el uso de proveedores de notificaciones, bien componentes locales como PushSharp, en la nube como Azure Hub Notifications o Firebase Cloud Messaging, cualquiera de ellos vas a necesitar la versión del certificado push en formato p12 junto con una clave que ahora veremos.

Lo primero es dirigirnos al llavero del Mac y exportar nuestro certificado "Apple Push Services" que hemos generado y acabamos de ver en el capítulo anterior.


Primero seleccionamos el certificado a exportar, luego pulsamos sobre el menú "Archivo" y seleccionamos la opción "Exportar items...", veremos la siguiente pantalla.


Tan solo nos quedaría teclear el nombre para el certificado y elegir la contraseña segura y apropiada, esta contraseña tenéis que anotarla porque nos hará falta en el siguiente paso. Llegado a este punto ya tenemos en nuestro poder el fichero con extensión .p12 y nuestra clave, vuelvo a recalcar, importante tener a mano estas dos cuestiones: fichero p12 y la contraseña.

Proveedores de servicio de notificaciones push

Como hemos comentado anteriormente, una vez preparada toda la parte de la arquitectura de cliente, ahora necesitamos del componente servidor que será el encargado de realizar el envío de las notificaciones push hacia los dispositivos que recepcionarán los mensajes.

Push Sharp

Se trata de un componente de Nuget que podemos instalar directamente en nuestro proyecto del lado servidor, aquí tienes su sitio web: https://github.com/Redth/PushSharp, es sencillo tanto de instalar como de utilizar.

Aquí os dejo, un ejemplo de código para el envío de una notificación a dispositivos iOS de Apple haciendo uso del componente Push Sharp.


            var pathCertificate = @"<PATH_PROYECT>\Certificates\dummy-push-dev.p12";

            // Configuration (NOTE: .pfx can also be used here)
            var config = new ApnsConfiguration(ApnsConfiguration.ApnsServerEnvironment.Sandbox,
                pathCertificate, "12345678");

            // Create a new broker
            var apnsBroker = new ApnsServiceBroker(config);

            // Wire up events
            apnsBroker.OnNotificationFailed += (notification, aggregateEx) => {
                Debug.Write("Error to try send push");
            };

            apnsBroker.OnNotificationSucceeded += (notification) => {
                Debug.Write("Push sended ok");
            };

            // Start the broker
            apnsBroker.Start();

            // Queue a notification to send
            apnsBroker.QueueNotification(new ApnsNotification
            {
                DeviceToken = deviceToken,
                Payload = JObject.FromObject(new
                {
                    aps = new
                    {
                        alert = message,
                        sound = "default",
                        badge = 1,
                        parameters = parameters
                    }
                })
            });

            // Stop the broker, wait for it to finish 
            // This isn't done after every message, but after you're
            // done with the broker
            apnsBroker.Stop();

Fíjate que el código hace referencia al DeviceToken, justamente el que mencionamos anteriormente que debíamos guardar en el servidor (backend).

El uso de este componente tiene sus limitaciones, ten en cuenta que si nuestro proyecto va a tener un uso considerable de notificaciones conllevará un consumo de recursos, lo que será difícil escalar, además que todo el peso del proceso de envío recaerá en nuestra responsabilidad, en la capa y componente servidor que hayamos elegido.

Para un mejor escalado y redimensionado de nuestra aplicación existen otras opciones como la integración con Azure Hub Notifications que veremos en otro post.

Requisitos indispensables

Para las pruebas de las notificaciones será necesario un dispositivo físico real: iPhone, iPod o iPad, ya que el simulador no dispone de esta característica, además para el despliegue en un dispositivo físico será necesario que estes adherido como developer de Apple, al menos en la versión individual, si tienes duda sobre esto puedes consultar la entrada en el post que ya hablamos sobre ello:

Puedes descargar el proyecto completo en GitHub y hacer pruebas, aquí tienes toda la información:



Comentarios

Entradas populares de este blog

Qué necesito para ser desarrollador de aplicaciones móviles (2ª parte)

Notificaciones agrupadas en iOS