image


indigitall Android SDK


Índice

  1. Introducción
    1. Obtención del “App Token” de la aplicación
    2. Obtención del “Sender ID” y “Api Key” de la aplicación
  2. Integración
    1. Estructura del proyecto en xamarin
    2. SDK de indigitall
      1. Importación mediante Nuget
    3. Configuración del Proyecto de Android
      1. Configuración de Paquetes para Android
      2. Configuración del AndroidManifest
    4. Configuración del Proyecto de iOS
      1. Configuración de Capabilities
      2. Configuración de Info.plist
      3. Inclusión del Notification Service Extension
  3. Uso del SDK
    1. Inicialización del SDK
    2. Sincronización con el registro del dispositivo
    3. Clases del SDK
    4. Funciones disponibles del SDK
    5. Capturar el click sobre la Push
    6. Capturar push
    7. Servicio de External Apps
    8. Notificaciones con GIF
    9. Recoger DeviceID
  4. F.A.Q
  5. Contacto

1. Introducción

En este documento se muestra toda la información necesaria para realizar la integración del SDK de Indigitall en una aplicación desarrollada en Xamarin. En él se muestra todo lo necesario para integrar el SDK en una aplicación ya existente para poder utilizar los servicios que ofrece la plataforma indigitall.

Es importante consultar este manual antes de realizar el desarrollo y seguir todos los pasos que en él se indican para garantizar el correcto funcionamiento de la integración. El documento está dirigido a desarrolladores Android, por lo que se utilizará un lenguaje técnico y se mostrarán ejemplos de código fuente cuando sea necesario.

1.1. Obtención del "App Token" de la aplicación

Cada aplicación registrada en el Panel de Control de Indigitall dispondrá de un identificador único denominado App Token. Este identificador se utilizará para inicializar el SDK y será el responsable de vincular la aplicación con la plataforma de indigitall, de esta forma indicará a qué aplicación pertenecen las notificaciones que lleguen al dispositivo. El App Token de una aplicación puede ser obtenido desde el Panel de Control de indigitall por un usuario administrador en el apartado de “Detalles” de la aplicación.

1.2. Obtención del “Sender ID” y “Api Key” de la aplicación

Anteriormente, para que la aplicación pudiera recibir notificaciones con la herramienta GCM de Google, se necesitaban unos identificadores llamados Sender ID y Api Key. Actualmente, con la nueva herramienta FCM de Google, estos parámetros son llamados “ID del remitente” y “Clave del servidor”, aunque seguiremos llamándolos Sender ID y Api Key para facilitar el trabajo a los usuarios que ya los tengan de GCM.

Estos identificadores se utilizarán en el SDK para conectar la herramienta GCM/FCM de Google con los dispositivos que instalen la aplicación.

En el siguiente enlace explicamos cómo obtener estos identificadores para GCM y FCM.

2. Integración

2.1 Estructura del proyecto en xamarin

Los proyectos de Xamarin incluyen por asi decirlo tres proyectos en uno, el proyecto principal escrito en lenguaje .NET, y los proyectos generados para cada una de las plataformas nativas Android e IOS. La manera más sencilla de verlo es con un ejemplo:

Como se puede observar en la siguiente imagen tenemos 3 proyectos:

  1. El proyecto principal (PruebaIndigitall)
  2. Los proyectos que generan las apps nativas a partir de .NET:
    • Para Android sería PruebaIndigitall.Android
    • Para iOS sería PruebaIndigitall.iOS

estructura

2.2. SDK de indigitall

La librería de indigitall consiste en una serie de paquetes de Nuget (.nupkg):

  • Indigitall.Xamarin.PLC: Librería con la declaración de todos los métodos en lenguaje .NET que deben estar implementados en el Indigitall.Xamarin.Android e Indigitall.Xamarin.iOS

  • Indigitall.Xamarin.Android: Librería que realiza la traducción entre el código deL SDK para Android mediante un interfaz en .NET.

  • Indigitall.Xamarin.iOS: Librería que realiza la traducción entre el código deL SDK para IOS mediante un interfaz en .NET.

  • Indigitall.Android: El SDK de Android que consiste en un archivo .aar

  • Indigitall.iOS: El SDK de IOS que consiste en un archivo .framework

2.2.1 Importación mediante Nuget

Consiste en obtener las librerías mediante el repositorio de Nuget. Para ello deberemos seguir los siguientes pasos:

  • Añadir la librería al proyecto principal:

    La librería Indigitall.Xamarin.PLC debe añadirse al proyecto principal PruebaIndigitall en la sección de "Dependencies". Para ello pulsamos con el botón derecho sobre la sección "Dependencies" y seleccionamos "Add Packages...". Tras esto hacemos una búsqueda por Indigitall y seleccionamos para añadir el paquete Indigitall.Xamarin.PLC en la versión 3.3.0:

    anyadir_PLC

    El paquete se añadirá a la carpeta "NuGet" dentro de "Dependencies":

    NuGet

  • Añadir librerías al proyecto de Android:

    Al proyecto PruebaIndigitall.Android, se le añadirán las siguientes librerías en la sección de "Packages" :

    • Indigitall.Xamarin.PLC v3.3.0.1
    • Indigitall.Xamarin.Android v3.3.0.3
    • Indigitall.Android v3.3.0

    Los paquetes serán añadidos de la misma manera que el punto anterior:

    anyadir_Android

    Los paquetes deberán aparecer en la carpeta "Package":

    Packages_Android

  • Añadir librerías al proyecto de iOS:

    Al proyecto PruebaIndigitall.iOS, se le añadirán las siguientes librerías en la sección de "Packages" :

    • Indigitall.Xamarin.PLC v3.3.0.1
    • Indigitall.Xamarin.iOS v3.2.6
    • Indigitall.iOS v3.2.6.1

    Los paquetes se añadirán de la misma manera que para el proyecto de Android:

    xamarin_packages_ios_1

    Los paquetes deberán aparecer en la carpeta "Package":

    xamarin_packages_ios_2

2.3. Configuración del Proyecto de Android

2.3.1 Configuración de Paquetes para Android

Para poder usar la librería de indigitall se deben añadir al proyecto una serie de paquetes, además de los propios del SDK. Estos paquetes deberán añadirse en Packages del proyecto de Android (PruebaIndigitall.Android) con las versiones que indicamos más abajo:

  • Square.Okhttp3 (3.8.1)
  • Square.Okhttp (2.7.5)
  • Square.OkIO (1.13.0)
  • Square.Picasso (2.5.2.1)
  • System.Runtime (4.3.0)
  • System.Runtime.Serialization.Primitives (4.3.0)
  • System.ServiceModel.Primitives (4.5.3)
  • Xamarin.Forms (3.1.0.697729)
  • Xamarin.Android.Support.v4 (27.0.2.1)
  • Xamarin.Android.Support.Design (27.0.2.1)
  • Xamarin.Android.Support.v7.AppCompat (27.0.2.1)
  • Xamarin.Android.Support.v7.CardView (27.0.2.1)
  • Xamarin.Android.Support.v7.MediaRouter (27.0.2.1)
  • Xamarin.GooglePlayServices.Base (60.1142.1)
  • Xamarin.GooglePlayServices.Basement (60.1142.1)
  • Xamarin.GooglePlayServices.Gcm (60.1142.1)
  • Xamarin.GooglePlayServices.Iid (60.1142.1)
  • Xamarin.GooglePlayServices.Tasks (60.1142.1)
  • Xamarin.GooglePlayServices.Location (60.1142.1)

2.3.2 Configuración del AndroidManifest

El siguiente paso es configurar el archivo AndroidManifest del proyecto de Android (PruebaIndigitall.Android) y que se encuentra dentro de la carpeta Properties. En él se establecerán los permisos, servicios y receptores necesarios para recibir las notificaciones correctamente.

Lo primero que haremos será setear los parámetros principales de nuestra aplicación, desde la pestaña Application. Como se indica en la imagen desde esta pestaña podrémos indicar el nombre de la app, el nombre del paquete, el icono de la app, etc. El usuario deberá setear en este punto de forma obligatoria:

  • Minimum Android version: Android 4.1 (API level 16)
  • Target Android version: Android 8.0 (API level 26)

De forma que la pestaña Application del AndroidManifest quede configurada de la siguiente manera:

app_parmas

Para empezar hay que añadir los permisos necesarios para la correcta ejecución de la aplicación y la utilización de la librería de GCM es necesario situarnos en la pestaña Source del AndroidManifest para poder ver el XML. Los permisos a añadir son los siguientes:

<!-- Permisos Obligatorios-->
<permission android:name="{yourpackage}.permission.C2D_MESSAGE"
    android:protectionLevel="signature" />
<uses-permission android:name="{yourpackage}.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE"/>

<!-- Permisos Opcionales -->
<!--Permisos de Localización-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!--Permisos del Teléfono-->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE"/>

Los dos primeros permisos aseguran que únicamente esta aplicación podrá recibir los mensajes, el siguiente permite la recepción en sí de mensajes desde GCM (es necesario sustituir {yourpackage} por el nombre de paquete propio que se utilice en la aplicación). Los permisos de localización y de telefonía son opcionales y se utilizan para traquear la posición del usuario y realizar llamadas respectivamente en caso de que se vayan a usar estas funciones de indigitall.

Es necesario declarar una serie de servicios dentro de la aplicación para que ésta pueda hacer un uso correcto de la librería de indigitall. Son los siguientes:

<!-- Start indigitall Services -->
<!-- Servicios Android 8-->
<service android:name="net.indigitall.pushsdk.service.IndigitallJobService"
   android:permission="android.permission.BIND_JOB_SERVICE"/>
<service android:name="net.indigitall.pushsdk.service.LocationJobService"
   android:permission="android.permission.BIND_JOB_SERVICE"/>
<service android:name="net.indigitall.pushsdk.service.GCMIntentJobService"
      android:permission ="android.permission.BIND_JOB_SERVICE"/>
<service android:name="net.indigitall.pushsdk.service.GifJobService"
        android:permission ="android.permission.BIND_JOB_SERVICE"/>
<!-- Fin servicios Android 8-->

<service android:name="net.indigitall.pushsdk.service.IndigitallService"/>
<service android:name="net.indigitall.pushsdk.service.NotificationService"/>
<service android:name="net.indigitall.pushsdk.service.LocationService"/>
<service android:name="net.indigitall.pushsdk.GCMIntentService"/>
<service android:name="net.indigitall.pushsdk.service.GifService"/>
<!-- End indigitall Services -->

También, como componentes de la aplicación, se deben declarar una serie de BroadcastReceiver llamados GCMBroadcastReceiver e IndigitallBroadcastReceiver (estos ya vienen implementados en la librería de Indigitall). Tan solo es necesario modificar el elemento del GCMBroadcastReceiver para indicar el nombre del paquete java.

<!-- Start indigitall Receivers -->
<receiver android:name="net.indigitall.pushsdk.broadcast.GCMBroadcastReceiver"
    android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <action android:name="com.google.android.c2dm.intent.REGISTRATION"/>
        <category android:name="{yourpackage}" />
    </intent-filter>
</receiver>

<receiver android:name="net.indigitall.pushsdk.broadcast.IndigitallBroadcastReceiver"
    android:enabled="true"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</receiver>
<!-- End indigitall Receivers -->

2.4 Configuración del Proyecto de iOS

2.4.1 Configuración de Capabilities

Se deben activar las Capabilities de Push Notifications y de Background Modes, en la cual se seleccionarán Location updates, Background fetch y Remote notifications.

image image

También se deberá activar la capability App Groups y seleccionar el grupo que haya creado desde la consola de App. Esta capability deberá quedar configurada de la siguiente manera:

image

2.4.2 Configuración de Info.plist

El siguiente paso es configurar el archivo Info.plist del proyecto. En él se establecerán las siguientes claves en el apartado Origin:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>indigitall.net</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSTemporaryExceptionMinimumTLSVersion</key>
            <string>TLSv1.1</string>
        </dict>
    </dict>
</dict>

2.4.3 Inclusión del Notification Service Extension

A partir de iOS 10 se mejoran las opciones y el control de las notificaciones. Para poder hacer uso de estas mejoras es necesario incluir un nuevo módulo en el proyecto llamado Notification Service Extensión.

image

image

En la configuración de la extensión es necesario que en la sección Deployment Info, el campo Deployment Target este configurado a 10.0. Esto configura cual es la versión minima del S.O. a la que se da soporte:

image

Deberán activarse también la Capability App Group para el Notification Extension Manager y seleccionar el grupo que se haya creado para la app en la consola de Apple "group.net.MyApp".

Tras haber creado el NSE será necesario sustituir el contenido del archivo NotificationService.cs por el siguiente:

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using Foundation;
using UIKit;
using UserNotifications;

namespace Notification
{

    [Register("NotificationService")]
    public class NotificationService : UNNotificationServiceExtension
    {
        const string groupName = "group.net.myApp";
        const string serviceURL = "https://apinotificaciones.indigitall.net";
        const string serviceEndpoint = "/status";

        Action<UNNotificationContent> ContentHandler { get; set; }
        UNMutableNotificationContent BestAttemptContent { get; set; }

        string idAps { get; set; }
        string titleAps { get; set; }
        string descriptionAps { get; set; }

        protected NotificationService(IntPtr handle) : base(handle)
        {
            // Note: this .ctor should not contain any initialization logic.
        }

        public override void DidReceiveNotificationRequest(UNNotificationRequest request, Action<UNNotificationContent> contentHandler)
        {
            ContentHandler = contentHandler;
            BestAttemptContent = (UNMutableNotificationContent)request.Content.MutableCopy();

            if (this.BestAttemptContent != null)
            {
                this.BestAttemptContent.Title = "";

                NSDictionary aps = (NSDictionary)request.Content.UserInfo.ObjectForKey(new NSString("aps"));
                if (aps == null)
                {
                    this.contentComplete();
                    return;
                }

                string title = aps.ObjectForKey(new NSString("title")).ToString();
                if (title != null)
                {
                    this.BestAttemptContent.Title = title;
                }

                string description = aps.ObjectForKey(new NSString("description")).ToString();
                if (description != null)
                {
                    this.BestAttemptContent.Body = description;
                }

                NSDictionary userInfo = request.Content.UserInfo;
                if (userInfo != null) {
                    this.manageUserInfo(userInfo, aps);
                }
            }
        }

        public override void TimeWillExpire()
        {
            this.contentComplete();
        }

        private void contentComplete()
        {
            ContentHandler(BestAttemptContent);
        }

        private void manageUserInfo(NSDictionary userInfo, NSDictionary aps)
        {
            NSDictionary payload = new NSMutableDictionary();
            var dataPayload = userInfo.ObjectForKey(new NSString("u"));
            if (dataPayload != null && dataPayload is NSString)
            {
                NSData data = NSData.FromString(dataPayload.ToString());
                NSError err = null;
                NSJsonSerialization.Deserialize(data, 0, out err);
            }
            else if (dataPayload != null && dataPayload is NSDictionary)
            {
                payload = (NSDictionary)dataPayload;
            }

            // Identifier
            string identifier = "";
            string identifierId = payload.ObjectForKey(new NSString("id")).ToString();
            if (identifierId != null)
            {
                identifier = identifierId;
                this.traceEventsForMessageId(identifier);
                this.interactivePush(payload);
            }

            // Image

            string image = aps.ObjectForKey(new NSString("img-ios")).ToString();

            string gif = aps.ObjectForKey(new NSString("gif_url")).ToString();
            if (gif != null)
            {
                image = gif;
            }

            if (image != null)
            {
                NSUrl imageURL = new NSUrl(image);
                NSUrlSessionTask task = NSUrlSession.SharedSession.CreateDownloadTask(imageURL, (NSUrl location, NSUrlResponse response, NSError error) =>
                {
                    if (location != null)
                    {
                        NSUrl temporaryDirectory = NSFileManager.DefaultManager.GetTemporaryDirectory(); // Environment.GetFolderPath(Environment.SpecialFolder.Personal);

                        string tmpFile = temporaryDirectory.AbsoluteString + imageURL.LastPathComponent;
                        NSUrl tmpURL = new NSUrl(tmpFile);
                        error = null;
                        if (NSFileManager.DefaultManager.Move(location, tmpURL, out error))
                        {
                            error = null;
                            UNNotificationAttachment attachment = UNNotificationAttachment.FromIdentifier(identifier, tmpURL, new UNNotificationAttachmentOptions(), out error);
                            if (attachment != null)
                            {
                                this.BestAttemptContent.Attachments = new UNNotificationAttachment[] { attachment };
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("Image error: " + error.LocalizedDescription);
                    }
                    this.contentComplete();
                });
                task.Resume();
            }
            else
            {
                this.contentComplete();
            }
        }

        private void interactivePush(NSDictionary payload)
        {
            string subtype = payload.ObjectForKey(new NSString("y")).ToString();
            int subtypeInt = 0;
            if (subtype != null)
            {
                subtypeInt = int.Parse(subtype);
            }
            if (subtypeInt == 11 || subtypeInt == 12)
            {
                string categoryId = payload.ObjectForKey(new NSString("c")).ToString();
                int categoryInt = 0;

                if (categoryId != null)
                {
                    categoryInt = int.Parse(categoryId);
                }

                if (categoryInt != 0)
                {
                    string title1 = "", title2 = "", category = "";

                    switch (categoryInt)
                    {
                        case 1:
                            title1 = "Si";
                            title2 = "No";
                            category = "InteractiveYesNo";
                            break;
                        case 2:
                            title1 = "Aceptar";
                            title2 = "Cancelar";
                            category = "InteractiveAcceptReject";
                            break;
                        case 3:
                            title1 = "Descargar";
                            category = "InteractiveDownload";
                            break;
                        case 4:
                            title1 = "Compartir";
                            category = "InteractiveShare";
                            break;
                        case 5:
                            title1 = "Seguir";
                            category = "InteractiveFollow";
                            break;
                        default:
                            break;
                    }

                    var actions = new List<UNNotificationAction>();

                    if (!title1.Equals(""))
                    {
                        string textButton = payload.ObjectForKey(new NSString("txt")).ToString();
                        if (textButton != null) title1 = textButton;
                        actions.Add(UNNotificationAction.FromIdentifier("0", title1, UNNotificationActionOptions.Foreground));
                    }

                    if (!title2.Equals(""))
                    {
                        string textButton = payload.ObjectForKey(new NSString("tbt")).ToString();
                        if (textButton != null) title2 = textButton;
                        actions.Add(UNNotificationAction.FromIdentifier("1", title2, UNNotificationActionOptions.Foreground));
                    }

                    UNNotificationCategory notificationCategory = UNNotificationCategory.FromIdentifier(category, actions.ToArray(), new string[] { }, UNNotificationCategoryOptions.None);
                    NSSet<UNNotificationCategory> categories = (NSSet<UNNotificationCategory>)new NSSet(notificationCategory);
                    UNUserNotificationCenter.Current.SetNotificationCategories(categories);
                    this.BestAttemptContent.CategoryIdentifier = category;
                }
            }
        }

        private void traceEventsForMessageId(string messageId)
        {
            NSUserDefaults defaults = new NSUserDefaults(groupName);
            string appToken = defaults.StringForKey(new NSString("s6txzqMVYq75XjLJ"));
            string deviceID = this.uniqueGlobalDeviceIdentifier();

            if (appToken != null && deviceID != null)
            {
                NSMutableDictionary dictionary = new NSMutableDictionary();
                dictionary.SetValueForKey(new NSString(appToken), new NSString("app_token"));
                dictionary.SetValueForKey(new NSString(deviceID), new NSString("device_id"));
                dictionary.SetValueForKey(new NSString(messageId), new NSString("message_id"));
                dictionary.SetValueForKey(new NSString("11"), new NSString("push_status"));

                this.sendTraceWithParams(dictionary);
            }
        }

        private void sendTraceWithParams(NSDictionary parameters)
        {
            string urlString = serviceURL + serviceEndpoint;

            string fullMutableString = urlString;
            string joiner = "?";
            foreach (NSObject key in parameters.Keys)
            {
                string value = parameters[key].ToString();
                fullMutableString = fullMutableString + joiner + key + "=" + value;
                joiner = "&";
            }

            string fullURL = NSUrlUtilities_NSString.CreateStringByAddingPercentEncoding(new NSString(fullMutableString), NSUrlUtilities_NSCharacterSet.UrlFragmentAllowedCharacterSet).ToString();
            NSUrl url = new NSUrl(fullURL);

            NSMutableUrlRequest request = new NSMutableUrlRequest(url);
            request.HttpMethod = "GET";

            NSUrlSession session = NSUrlSession.SharedSession;
            session.CreateDataTask(request, (NSData data, NSUrlResponse response, NSError error) => {
                Console.WriteLine("Status from extension: " + ((NSHttpUrlResponse)response).StatusCode);
            }).Resume();
        }

        private string uniqueGlobalDeviceIdentifier()
        {
            NSUuid identifierForVendor = UIDevice.CurrentDevice.IdentifierForVendor;
            string deviceID = identifierForVendor.AsString();
            return deviceID;
        }
    }
}

Este group también deberá setearse en el código del NSE, concretamente en el archivo NotificationService.cs en la siguiente constante:

  const string groupName = "group.net.myApp";

3. Uso del SDK

Para poder utilizar la librería es necesario tener el APP_TOKEN de indigitall para la aplicación y darla de alta en el servicio GCM/FCM de Google para obtener el API_KEY y el SENDER_ID.

3.1 Inicialización del sdk

3.1.1 Android

La inicialización de la librería debe llevarse a cabo en el proyecto principal (PruebaIndigitall) en la clase App.xaml.cs despues de cargar la pagina principal

using Xamarin.Forms.Xaml;
using Net.Indigitall.Xamarin.PCL;
using Xamarin.Forms;

namespace PruebaIndigitall.Droid
{

    [Activity(Name = "YOUR_APP_PACKAGE.MainActivity", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {

      protected override void OnCreate(Bundle savedInstanceState)
      {

           base.OnCreate(savedInstanceState);

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

            //Datos para inicializar indigitall
            string app_token = "YOUR_APP_TOKEN";
            bool external_apps = false;
            string sender_id = "YOUR_SENDER_ID";
            string mainActivity = "YOUR_APP_PACKAGE" + ".MainActivity";

            //Ajustes del SDK
            string bigIcon = "ic_launcher"; //Seteo del icono de la push
            string smallIcon = "ic_small"; //Seteo del icono monocromo
            string smallIconColor ="#2B84D2"; //Seteo del color de fondo del icono monocromo

             IndigitallHelper indigitall = new IndigitallHelper();
              if (indigitall != null)
              {
                  indigitall.init(
                      app_token,
                      external_apps,
                      sender_id,
                      mainActivity,
                      bigIcon,
                      smallIcon,
                      smallIconColor
                  );
              }
        }
    }
}

Ajustes de la librería

Para el seteo de los ajustes de la librería podemos indicarle:

  • El icono de nuestra aplicación para visualizarlo en las notificaciones (variable bigIcon).
  • El icono para la barra de notificaciones que aparece en Android 5.0 o superior (smallIcon). * El color que queremos que tenga este último icono en las notificaciones (smallIconColor). En el código se corresponden con:

    //Ajustes del SDK
    string bigIcon = "ic_launcher"; //Seteo del icono de la push
    string smallIcon = "ic_small"; //Seteo del icono monocromo
    string smallIconColor ="#2B84D2"; //Seteo del color de fondo del icono monocromo

    Todos estos ajustes se pasan como parámetros en la inicialización de la librería y sus recursos deben existir como objetos drawables en la carpeta de Recursos del proyecto de Android (PruebaIndigitall.Android) tal como se muestra en la siguiente imagen:

settings_xamarin

3.1.1 iOS

Para inicializar la librería es necesario añadir en el método FinishedLaunching del AppDelegate.cs el siguiente código. Se debe incluir el 'APP_TOKEN' proporcionado por Indigitall y además indicar si se quiere dar soporte a aplicaciones de terceros.

public override bool FinishedLaunching(UIApplication uiApplication, NSDictionary launchOptions)
{
        global::Xamarin.Forms.Forms.Init();
        LoadApplication(new App());

        IndigitallLib.SharedInstance.SetGroupName("group.net.myApp");
        IndigitallLib.SharedInstance.InitializeWithAppToken("APP_TOKEN", false);

        return base.FinishedLaunching(uiApplication, launchOptions);
}

En el momento de la inicialización si la aplicación aún no ha solicitado el permiso de notificaciones el SDK se encargará de solicitar al usuario ese permiso.

Para el correcto funcionamiento de las notificaciones hay que incluir el siguiente código en el AppDelegate.cs:

public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
        IndigitallLib.SharedInstance.DidRegisterForRemoteNotificationsWithDeviceToken(deviceToken);
}

public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{
        IndigitallLib.SharedInstance.DidFailToRegisterForRemoteNotificationsWithError(error);
}

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

public override void ReceivedRemoteNotification(UIApplication application, NSDictionary userInfo)
{
        IndigitallLib.SharedInstance.DidReceiveRemoteNotification(userInfo);
}

public override void HandleAction(UIApplication application, string actionIdentifier, NSDictionary remoteNotificationInfo, Action completionHandler)
{
        IndigitallLib.SharedInstance.HandleActionWithIdentifier(actionIdentifier, remoteNotificationInfo, completionHandler);
}

3.2 Sincronización con el registro del dispositivo

3.2.1 Android

Para evitar posibles conflictos con el registro del dispositivo, como realizar acciones que requieran el deviceId del dispositivo (que se genera durante el registro), Indigitall provee de un listener que permite saber cuando dicho registro se ha completado.

Para ello es necesario hacer que la Activity implemente IReadyListener y su método OnReady:

[Activity(Name = "YOUR_APP_PACKAGE.MainActivity", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
  public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IReadyListener
  {
    ...

        public void OnReady(DataModel data)
        {
          string deviceId = indigitall.getDeviceID();
          //Envia el deviceId a tu servidor
        }
    ...
  }

3.2.2 IOS

En iOS el DeviceID se genera al iniciar la app, por lo tanto se puede llamar al método de recoger el DeviceID en cualquier momento.

...

var deviceID = IndigitallLib.DeviceID;

...

3.3 Clases del SDK

La librería de indigitall proporciona una serie de clases para hacer más cómoda la interacción con ésta y facilitar la recogida e introducción de datos.

3.3.1 Android

En Android estas clases se dividen en dos grupos (Objetos y Listeners) y son los siguientes:

    /**
     * Objeto que recoge datos del dispositivo
     */
        using Net.Indigitall.Pushsdk.Model.DataModel;

        DataModel dataModel = new DataModel();

        // Recoge el identificador único de dispositivo de indigitall.
        string deviceId= dataModel.DeviceID;
        // Recoge la versión de la librería de indigitall.
        string vLibrary = dataModel.GetvLibrary();
        // Recoge el número de versión del SDK de Android.
        string vAndroidSDK = dataModel.GetvAndroidSDK();
        // Recoge el código de la versión de Android.
        string vAndroidCode = dataModel.GetvAndroidCode();
        // Recoge el nombre de la versión de Android.
        string vAndroidName = dataModel.GetvAndroidName();
        // Recoge el nombre del fabricante.
        string brandName = dataModel.BrandName;
        // Recoge el nombre del modelo.
        string modelName = dataModel.ModelName;
        // Recoge el código del dispositivo.
        string deviceCode = dataModel.DeviceCode;
        // Recoge el nombre de la compañía si tiene permisos de telefonía.
        string carrierName = dataModel.CarrierName;

    /**
     * Objeto que recoge los datos de las Push enviadas.
     */
         using Net.Indigitall.Pushsdk.Model.PushModel;

         PushModel push = new PushModel();
         // Devuelve el identificador de la push.
         int id = push.Id;
         // Devuelve el tipo de la push.
         int type = push.Type;
         // Devuelve el subtipo de la push.
         int subtype = push.Subtype;
         // Devuelve el título de la push.
         string title = push.Title;  
         // Devuelve el cuerpo de la push.
         string body = push.Body;
         // Devuelve la URL del icono de la push si se ha establecido.
         string iconURL = push.IconURL;
         // Devuelve la URL de la imagen de la push si se ha establecido.
         string imageURL = push.ImageURL;
         // Devuelve la URL del GIF de la push si se ha establecido
         string gifURL = push.GifURL;
         // Devuelve los datos de la push enviados a la app si se han establecido.
         string data = push.Data;

    /**
     * Objeto que recoge o establece los datos de los Tags para manejarlos.
     */
        using Net.Indigitall.Pushsdk.Model.TagModel;

        TagModel tag = new TagModel();

        tag.Id = "Tag_Id";  // Establece el identificador del tag.
        string Id = tag.Id;// Devuelve el identificador del tag.

        tag.Name = "Tag_Name";// Establece el nombre del tag.
        string Name = tag.Name;  // Devuelve el nombre del tag.

        tag.Parent = "Tag_Parent"; // Establece el padre del tag.
        string Parent = tag.Parent; // Devuelve el padre del tag.

        tag.Subscribe = true; // Establece si el dispositivo se ha suscrito al tag.
        bool isSubscribe = tag.Subscribe;  // Devuelve si el dispositivo se ha suscrito al tag.

    /**
     * Listener que controla la recogida de datos del dispositivo.
     * Tipo: interface.
     */
      Net.Indigitall.Pushsdk.Listeners.IDataListener {
          // Método llamado cuando se recogen los datos del dispositivo.
          void OnGetDeviceData(DataModel deviceData);
          // Método llamado cuando se recoge el deviceID (identificador único de indigitall).
          void OnGetDeviceID(string deviceID);
      }

    /**
     * Listener que controla la recogida de datos del dispositivo.
     * Tipo: abstract class implements IDataListener.
     */
      Net.Indigitall.Pushsdk.Listeners.AbstractDataListener {
          // Método que implementa #IDataListener.onGetDeviceData(deviceData).
          void OnGetDeviceData(DataModel deviceData);
          // Método que implementa #IDataListener.onGetDeviceID(deviceID).
          void OnGetDeviceID(string deviceID);
      }

    /**
     * Listener que controla el estado del dispositivo para recibir notificaciones.
     * Tipo: interface.
     */
      Net.Indigitall.Pushsdk.Listeners.IDeviceStatusListener {
          // Método llamado cuando se recibe el estado del dispositivo.
          void OnChangeDeviceStatus(bool isDisabled);
      }

    /**
     * Listener que controla el manejo de los Tags.
     * Tipo: interface.
     */
      Net.Indigitall.Pushsdk.Listeners.ITagsListener {
          // Método llamado cuando se recibe el listado de tags de la aplicación.
          void OnGetTagsList(IList<TagModel> tagList);
          // Método llamado cuando se reciben los tags a los que está suscrito el dispositivo.
          void OnGetTagsSubscriptions(IList<TagModel> tagList);
          // Método llamado cuando se suscribe el dispositivo a uno o varios tags.
          void OnSubscribe(boolean wasSubscribed);
          // Método llamado cuando se desinscribe el dispositivo de uno o varios tags.
          void OnUnsubscribe(boolean wasUnsubscribed);
      }

    /**
     * Listener que controla la sincronización con el registro.
     * Tipo: interface.
     */
      Net.Indigitall.Pushsdk.Listeners.IReadyListener {
          // Método llamado cuando se termina el registro del dispositivo.
          void OnReady(DataModel data);
      }

3.3.2 iOS

En iOS se dividen en tres grupos (Constantes, Objetos y Delegates) y son los siguientes:

    /**
     * Constantes
     */
      using Net.Indigitall.iOS.Constants

      // Número de version del SDK de iOS
      double IndigitallVersionNumber
      // Nombre de versión del SDK de iOS
      NSString IndigitallVersion

    /**
     * Objeto que recoge los datos de las Push enviadas.
     */
      using Net.Indigitall.iOS.INPushNotification

      // Tipo de la notificación
      NSNumber Type
      // Subtipo de la notificación
      NSNumber Subtype
      // ID de la notificación
      string Message_id
      // Título de la notificación
      string Title
      // Cuerpo de la notificación
      string Body
      // URL de la imágen de la notificación
      string ImageURL
      // Campo que contiene una cadena de datos si estos se han establecido
      string Data
      // Acción de la notificación
      string Action
      // URL a abrir al pulsar el botón 1
      string UrlButton1
      // Texto mostrado en el botón 1
      string TitleButton1
      // URL a abrir al pulsar el botón 2
      string UrlButton2
      // Texto mostrado en el botón 2
      string TitleButton2
      // Categoría de la notificación
      NSNumber Category

3.4 Funciones disponibles del SDK

Indigitall provee de una serie de métodos para las aplicaciones que hagan uso de la librería. Estos métodos ofrecen funcionalidades que van desde poder suscribirse y manejar Tags hasta operaciones para habilitar o deshabilitar el dispositivo.

Los Tags han de estar previamente creados en el panel para poder listarlos, suscribirse o desinscribirse de ellos.

3.4.1 Android

Los métodos disponibles en la clase IndigitallHelper son los siguientes:

  • Estado del dispositivo: Los métodos para poder gestionar el estado del dispositivo para la recepción de notificaciones son:

    /**
     * Comprueba el estado del dispositivo para saber si recibe o no notificaciones.
     * Devuelve true si el dipositivo esta desactivado para recibir notificaciones y
     * false en caso contrario.
     */
     public bool IsDeviceDisabled();
    
    /**
     * Habilita el dispositivo para que le lleguen notificaciones.
     * Devuelve true si no hubo errores.
     */
    public bool EnableDevice();
    
    /**
     * Desahabilita el dispositivo para que no le lleguen notificaciones.
     * Devuelve true si no hubo errores.
     */
    public bool DisableDevice();
  • Localización: Los métodos para poder gestionar la localización son los siguientes:
    /**
     * Comprueba si el SDK esta habilitado o no para enviar localización.
     * Devuelve true si la localización esta activada y false en  caso contrario.
     */
    public bool isLocationEnabled();
    /**
     * Habilita la localización para que el SDK la envíe.
     * Devuelve true si no hubo errores.
     */
    public bool enableLocation();
    /**
     * Desahabilita la localización para que el SDK no la envíe.
     * Devuelve true si no hubo errores.
     */
    public bool disableLocation();
  • Tags: Para poder utilizar los métodos referentes a los tags o grupos de interés es necesario que la librería "indigitall" haya sido inicializada:

      //Listar los tags creados en el Panel
      indigitall.fetchAllTags();
      //Listar los tags a los que esta suscrito el dispositivo
      indigitall.fetchSubscribedTags();
      /**
      *Suscribir el dispositivo a los tags pasados como parámetro.
      * Parametro de entrada:  string[] tags -> Array de ids de los Tags
      **/
      indigitall.subscribe(tags);
      /**
      *Desuscribir el dispositivo a los tags pasados como parámetro
      * Parametro de entrada:  string[] tags -> Array de ids de los Tags
      **/
      indigitall.unsubscribe(tags);

    Para poder capturar las respuestas a los métodos anteriores es necesario que la Activity implemente el interfaz ITagsListener :

      [Activity(Name = "YOUR_APP_PACKAGE.MainActivity", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
      public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, ITagsListener
      {
          ...
    
      }

    Los métodos del interfaz que se deben implementar son:

      /**
       * Respuesta a la petición de la lista de tags creados en el panel.
       */
      public void OnGetTagsList(IList<TagModel> tagsPanel){
    
      }
    
      /**
       * Respuesta a la petición de la lista de tags a los que está suscrito el dispositivo.
       */
      public void OnGetSubscriptions(IList<TagModel> tagsDevice){
    
      }
      /**
       * Respuesta a la petición de suscripción.
       *
       */
       public void OnSubscribe(bool wasSubscribed){
         if(wasSubscribed){
           //Dispositivo suscrito correctamente
         }else{
           //Error al suscribir el dispositivo
         }
       }
      /**
       * Respuesta a la petición de desuscripción.
       * Devuelve un
       */
       public void OnUnsubscribe(bool wasUnSubscribed){
         if(wasUnSubscribed){
           //Dispositivo desuscrito correctamente
         }else{
           //Error al desuscribir el dispositivo
         }
       }
  • DeviceID:
    /**
     * Devuelve el identificador único de indigitall por dispositivo.
     */
    string deviceId = indigitall.getDeviceID();

    El método getDeviceID puede devolver un valor nulo la primera vez que se ejecuta la librería si aún no ha dado tiempo a que se genere.

3.4.2 iOS

Los métodos disponibles en la clase IndigitallHelper son los siguientes:

  • Estado del dispositivo: Los métodos para poder gestionar el estado del dispositivo para la recepción de notificaciones son:

    /**
     * Comprueba el estado del dispositivo para saber si recibe o no notificaciones.
     * Devuelve true si el dipositivo esta desactivado para recibir notificaciones y
     * false en caso contrario.
     */
     public bool IsDeviceDisabled();
    
    /**
     * Habilita el dispositivo para que le lleguen notificaciones.
     * Devuelve true si no hubo errores.
     */
    public bool EnableDevice();
    
    /**
     * Desahabilita el dispositivo para que no le lleguen notificaciones.
     * Devuelve true si no hubo errores.
     */
    public bool DisableDevice();

3.5 Capturar el click sobre la Push

Una vez que hemos realizado todo el proceso de registro e inicialización, la aplicación se encuentra en disposición de recibir los mensajes push, la librería se encargará de tratar los mensajes y mostrar las notificaciones adecuadas. La aplicación tendrá la posibilidad de recoger los datos de los mensajes push cuando se envíen notificaciones de tipo “Abrir App”.

3.5.1 Android

En Android la forma de recoger estos datos es gracias al Intent recibido por la MainActivity en los métodos onCreate y/o onResume de la siguiente forma del proyecto de Android (PruebaIndigitall.Android):


    [Activity(Name = "YOUR_APP_PACKAGE.MainActivity", Label = "PruebaIndigitall.Droid", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

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

            PushModel push = null;
            Intent intent = this.Intent;
            if (intent != null)
            {
                if (intent.HasExtra(PushModel.PushExtra))
                {
                    push = (PushModel) intent.GetParcelableExtra(PushModel.PushExtra);
                    string id = push.Data;
                    //Lanzar la Activity correspondiente al id enviado en la push
                }
            }

        }
    }

3.5.2 iOS

Proximamente...

3.6 Capturar Push

3.6.1 Android

En caso de quere capturar todos lo mensajes push que lleguen a la aplicación, el SDK de indigitall cuenta con un BroadcastReceiver que podrá sobreescribir y que se levantará cada vez que llegue una push. El PushBroadcastReceiver discriminará entre push de indigitall u otro servicio de notificaciones aportando un método a sobreescribir para cada caso.

Deberá sobreescribir y declarar el nuevo BroadcastReceiver de la siguiente forma:

    [BroadcastReceiver]
    [IntentFilter(new[] {"net.indigitall.action.PUSH_INDIGITALL", "net.indigitall.action.PUSH_OTHER" })]
    public class MyBroadcastReceiver : PushBroadcastReceiver
    {
        public MyBroadcastReceiver()
        {
        }

        public override void OnIndigitallPushReceived(PushModel p0)
        {
            Log.Debug("MyBroadcastReceiver", "OnIndigitallPushReceived");

        }

        public override void OnOtherPushReceived(Bundle p0)
        {
            Log.Debug("MyBroadcastReceiver", "OnOtherPushReceived");

        }
    }

3.6.2 iOS

Proximamente...

3.7 Servicio de External Apps

El servicio de external Apps permite enviar notificaciones en función de si el usuario tiene o no instalada una determinada aplicación. Para ello es necesario que queden definidas en el panel las aplicaciones que se desean comprobar.

3.7.1 Android

En el proyecto de Android para poder activar el servicio de externalApps será necesario poner la variable external_apps a true en la inicialización de la librería:

      ...
      bool external_apps = true;
      ...
      IndigitallHelper indigitall = new IndigitallHelper();
       if (indigitall != null)
       {
           indigitall.init(
               app_token,
               external_apps,
               sender_id,
               mainActivity,
               bigIcon,
               smallIcon,
               smallIconColor
           );
       }

3.7.2 iOS

Proximamente...

3.8 Notificaciones con GIF

3.8.1 Android

Para poder envíar notificaciones con GIF, es necesario declarar los siguientes servicios en el archivo AndroidManifest.xml:

<!-- Start indigitall Services -->
...
<service android:name="net.indigitall.pushsdk.service.GifJobService"
        android:permission ="android.permission.BIND_JOB_SERVICE"/>
<service android:name="net.indigitall.pushsdk.service.GifService"/>
<!-- End indigitall Services -->

Una vez declarado el servicio quedará activo y funcionando. Para envíar notificaciones de este tipo solo será necesario seguir los pasos que se indican en el manual de usuario del panel: Manual de usuario del Panel

3.9 Recoger DeviceID

3.9.1 Android

Cuando hablamos de DeviceID, nos referimos al identificador único que la librería de indigitall genera para identificar los dispositivos y poder enviarles mensajes push. Este ejemplo indica cómo recoger este dato para poder trabajar con él.

Es necesario que la Activity implemente el interfaz IDataListener

[Activity(Name = "YOUR_APP_PACKAGE.MainActivity", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, IDataListener
{
    ...

}

Los métodos del interfaz que se deben implementar son:

    public void OnGetDeviceData(DataModel deviceData)
    {
      // Método que proporciona los datos del dispositivo.
    }

    public void OnGetDeviceID(string deviceid)
    {
      // Método que proporciona el DeviceID
      sendToYourBackend(deviceID);
    }

3.9.2 IOS

Proximamente...

4. F.A.Q

  • Q: No llegan las notificaciones ¿Qué puedo hacer?
  • A: Busque en logs el siguiente mensaje “RegisterService: Device registered”. Si este mensaje llega es porque el registro de notificaciones se está efectuando correctamente. Si aún así no recibe notificaciones, revise su “App Token” y “Sender ID” y compruebe que sean correctos. Algunos dispositivos como Huawei y Xiaomi tienen economizadores de batería que evitan que lleguen correctamente las notificaciones. Si tiene un dispositivo de este tipo, configúrelo para recibir siempre notificaciones y, a poder ser, haga pruebas con la app en primer plano.

  • Q: ¿A qué versiones de Android da soporte indigitall?
  • A: La librería de indigitall se compila con minSdkVersion 16, por tanto la versión mínima de Android a la que da soporte es Jelly Bean (Android 4.1).

  • Q: La imagen me llega pequeña, ¿hay forma de arreglar esto?
  • A: Las notificaciones de indigitall pueden incluir dos imágenes, una imagen pequeña y cuadrada en el espacio del icono y una imágen grande panorámica debajo del cuerpo de la notificación. Las imágenes grandes sólo aparecen en las notificaciones de tipo foto. Revisar que, al crear el mensaje en el panel, la imágen se establece en su correspondiente campo y no en el del icono de la notificación.

  • Q: Me aparece un icono cuadrado en la barra de estado del dispositivo ¿por qué?
  • A: Desde Android 5.0 (Lollipop) el sistema utiliza un icono monocromo para representar las notificaciones de la aplicación en la barra de estado. Si este icono no se ha establecido manualmente, cogerá el icono por defecto de la aplicación, rellenándolo de color blanco y respetando únicamente las transparencias de éste. La librería de indigitall provee de métodos para configurar a gusto los iconos de las notificaciones. Ver sección Ajustes de la librería.

  • Q: No me llegan las notificaciones Geolocalizadas ¿cómo puedo arreglarlo?
  • A: Revise que tiene habilitada la geolocalización en el dispositivo y los permisos concedidos (en caso de ser Android 6.0 o superior). Abra la app y busque los logs correspondientes a “LocationManager” e “indigitallService”, en ellos podrá ver cómo cambia la localización y si esta es significativa. Hablamos de cambios significativos en la localización cuando el dispositivo se mueve más de 100 m de la última posición conocida. Este servicio se ejecuta cada 20 min por defecto, siendo posible modificar el tiempo en el panel de indigitall.

  • Q: ¿Es obligatorio que pida permisos de localización o telefonía a mis usuarios?
  • A: Los permisos de localización y de telefonía son opcionales, puedes excluirlos del manifest de la aplicación. En estos casos se pierden algunas funcionalidades relacionadas con estos permisos, como pueden ser las notificaciones Geolocalizadas y Geofencing o las notificaciones de tipo Click to Call.

  • Q: Mis notificaciones no se posicionan las primeras ¿Cómo hago que esto ocurra?
  • A: Las notificaciones de indigitall tienen la máxima prioridad que Android permite, las únicas notificaciones que pueden aparecer por encima son las que tengan la misma prioridad. En estos casos la notificación que llegue última será la que aparezca más arriba en el listado de notificaciones si ambas tienen la misma prioridad.

  • Q: ¿Cómo hago pruebas en desarrollo sin afectar a los usuarios de producción?
  • A: Los “App Token” de la aplicación de desarrollo y la de producción son distintos, esto es así para evitar que puedan llegarle a usuarios de producción notificaciones creadas en desarrollo. Por este motivo las pruebas en desarrollo no conllevan ningún riesgo. Aun así, siempre puede filtrar en el panel de indigitall por DeviceID creando y subiendo un .csv que contenga los identificadores de los dispositivos a los que quiere que llegue la notificación.

  • Q: ¿Cómo hago pruebas en producción sin afectar a los usuarios?
  • A: Las pruebas en producción son muy sensibles, ya que cometer un fallo aquí puede hacer que nuestra notificación llegue a usuarios reales. Por este motivo aconsejamos que a la hora de hacer pruebas en producción se hagan envíos geolocalizados o que se filtre por DeviceID como se explica en el caso anterior.

5. Contacto

En indigitall estamos encantados de ayudarle con cualquier duda o problema que le surja al integrar nuestra solución. Para contactar con nosotros puede escribirnos a soporte@indigitall.net. Nos pondremos en contacto con usted lo antes posible.