GUÍA DE INTEGRACIÓN

Swapkey

VERSIÓN

La presente es una guía para la versión 1.34 del Framework SwapkeyExtensionSDK con un proyecto desarrollado en Objetive C.

DESCARGA

El demo SwapkeyExtensionSDK se encuentra disponible para su descarga en el siguiente boton

REQUISITOS

Son requisitos indispensables:

AGREGANDO EXTENSIÓN DE TECLADO

Para agregar la extensión de teclado se deberá seleccionar dentro de la sección Project Navegator el nombre el proyecto, que es el elemento superior, después en la sección de “Targets” se deberá se deberá dar click en el botón “+”

Aparecerá una ventana nueva, en donde se debe elegir “Custom Keyboard Extension” que se encuentra dentro de la sección iOS -> Application Extension

Después se debe dar click en el botón “Next”.

Se deberá dar un nombre al Target y click en el botón “Finish”

Tal vez aparezca una ventana con título Activate “NombreTarget” scheme? Se deberá click en el botón “Activate”

Con lo anterior quedará listo el proyecto para la integración con SwapkeyExtensionSDK.

CLASE PRINCIPAL

Se deberá crear la clase principal para el teclado, seleccionando el folder correspondiente al target del proyecto, click derecha, crear nuevo archivo, seleccionar Cocoa Touch Class, en el espacio "Subclass of" se deberá rellenar: "UIInputViewController"

Puede ser que el archivo se haya generado automáticamente, de ser así, puede utilziarse ese.

El contenido del archivo, puede copiarse de aquí

Como segundo paso se deberá poner esta clase como clase principal. Para ello se deberá ir al archivo Info.plist del target del teclado, abrir la opción "NSExtension", y en el valor del renglón "NSExtensionPrincipalClass", se deberá colocar el nombre de la clase

INSTALACIÓN SDK

Para instalar el SDK se deberá hacer a través del siguiente pod:

pod 'SwapkeyExtensionSDK'

Después de integrar el pod al archivo podfile,  se deberá correr el comando install para ejecutar la instalación:

pod install

Para actualizar a la versión actual

pod update

EJEMPLO DE ARCHIVO PODFILE

Debido a que SwapkeyExtensionSDK se utlizará dentro de la Extensión de Keyboard y dentro de la aplicación contenedor o principal, el pod se deberá compartir en ambo targets, a continuación se muestra un ejemplo del archivo podfile, en donde se comparte el pod en ambos targets:

platform :ios, '8.0'
use_frameworks!

def swap_pods
        pod 'SwapkeyExtensionSDK'
end

target 'Demo' do
   swap_pods
end

target 'DemoKeyboard' do
   swap_pods
end

ACTIVANDO APP GROUPS

Para poder compartir información entre la aplicación contenedora (aplicación principal) y la extensión de teclado a través de UserDefaults, se debe activar el capability app groups en ambos targets.

  1. Para lo anterior se deberá seleccionar el elemento superior del Project Navegator
  2. Debajo de la sección Targets, seleccionar el target de la aplicación principal
  3. Seleccionar la sección Capabilities
  4. Habilitar el capability: App Groups
  5. Se deberá seleccionar un app group o en su defecto crear uno
  6. Se debe esperar unos segundo a que las opciones inferiores de la sección Steps se encuentre, las tres, con una palomita cada una
  7. Repetir los pasos anteriores seleccionando el target de la extensión de teclado

NOTA:

Es importante señalar que la aplicación principal o contenedor y la extensión de teclado deberán habilitarse con exactamente el mismo grupo, para que puedan compartir información entre sí.

ARCHIVOS AUXILIARES

Se deberán eliminar los archivos auxiliares utilizados anteriormente

ALMACENAMIENTO DE DEVICEID

La aplicación contenedora deberá compartir con la extensión el device ID a través de User Defaults del grupo activado anteriormente, el DeviceId, puede ser cualquier número que no se repita en ningún teléfono, por lo que se recomienda utilizar el nativo de Apple (Vendor ID). Un ejemplo para realizar esto se muestra a continuación:

-(void)setDeviceID
{
	UIDevice *device = [UIDevice currentDevice];
    NSString *uID = [[device identifierForVendor] UUIDString];
    uID = [uID stringByReplacingOccurrencesOfString:@"-" withString:@""];
    NSUserDefaults *def = [[NSUserDefaults alloc] @"NombreDelGrupoConfigurado"];
    NSString *key = [SKEOptions @"NombreDeVariableToStoreDeviceID"];
    [def setObject:uniqueIdentifier forKey:key];
    [def synchronize];
}

Es importante señalar que al inicializar los UserDefaults con la función initWithSuiteName se utilice el mismo nombre que se señalará posteriormente en la clase SKEPreferences.

De la misma manera al almacenar el deviceID, se debe enviar en el parámetro key, lo mismo que se indique posteriormente en la clase SKEPreferences

Lo anterior es para evitar errores ya que el sdk utilizará esas propiedades para obtener el user y el deviceID

Este será el único código que se agregará en la aplciación principal o contenedora

CONFIGURACION DEL SDK

La aplicación se configurará a través de la clase SKEPrefences, cuya instancia se enviará como parámetro al inicializar el SDK, para otener, modificar las preferencias se muestra el siguiente ejemplo:

SKEPreferences *pref = [SKEPreferences getCurrentPreferences];
    if (pref != nil)
    {
        pref.bundleGroup = @"group.SKE.Test";
        pref.selfUrlToOpen = @"swap://";
        pref.variableToStoreDeviceID = @"deviceID";
        pref.maxAttempsToPay = 3;
        pref.shouldShowSendKeyboard = YES;
        pref.notAllowedHosts = [[NSArray alloc] init];
        
        if ([Swapkey initializeWithKey:@"swap" isDevelopment:YES andPreferences:pref])
        {
            BOOL enabled = [Swapkey enableDebugging];
        }
    }

 1.- selfUrlToOpen

Con este parámetro se define algún scheme al que responda la aplicación y con el cual se pueda pedir al sistema operativo que abra la aplicación

Si no se tiene ninguno activado se pueden activar seleccionando desde el project navegator el proyecto principal -> Targets, la aplicación contenedora -> Info -> URL Types

En esta variable debe correponder a el scheme o url a la que responda la aplicación, en este caso “demo.ske://

pref.bundleGroup = @"demo.ske://";

2.- bundleGroup

En esta variable contener el bundle del grupo que se activó en uno de los pasos anteriores, en este caso: “group.swap.SKE

pref.bundleGroup = @"group.swap.SKE";

3.- variableToStoreDeviceID

En esta variable debe contener el key que se utilizará para guardar el device id en los user defaults, en este caso: “deviceID

pref.variableToStoreDeviceID = @"deviceID";

INICIALIZACIÓN DE SDK

En el archivo .h de la clase principal de la extensión "KeyboardViewController.h" se debe agregar la importación del SDK, con lo siguiente:

#import <SwapkeyExtensionSDK/SwapkeyExtensionSDK.h>
@class Swapkey;

Para inicializar el SDK, cuándo el usuario se ha registrado para utilizar el teclado, dentro de la aplicación, se deberá inicializar el SDK con el siguiente extracto de código:

[Swapkey initializeWithKey:@"swap" isDevelopment:YES andPreferences:pref];

El parámetro "isDevelopment" indica si se apunta a ambiente de desarrollo o producción.

Se deberá agregar a la clase "KeyboardViewController" la siguiente propiedad:

@property (nonatomic, strong) SwapkeyController *swapkeyController;

En la función "viewDidLoad", se deberá instanciar el objeto "swapkeyController" de la siguiente manera:

self.swapkeyController = [[SwapkeyController alloc] initWithHandler:self];
    [self.swapkeyController view];

En la función "updateViewConstraints" se deberá agregar la línea:

[self.swapkeyController updateViewConstraints];

Y en la función "textDidChange" se deberá agregar la línea:

[self.swapkeyController textDidChange:textInput];

De manera que el código completo de la clase "KeyboardViewController" quedaría:

#import "KeyboardViewController.h"

@interface KeyboardViewController ()
    @property (nonatomic, strong) UIButton *nextKeyboardButton;
    @property (nonatomic, strong) SwapkeyController *swapkeyController;
@end

@implementation KeyboardViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.nextKeyboardButton = [UIButton buttonWithType:UIButtonTypeSystem];
    
    SKEPreferences *pref = [SKEPreferences getCurrentPreferences];
    if (pref != nil)
    {
        pref.bundleGroup = @"group.SKE.Test";
        pref.selfUrlToOpen = @"swap://";
        pref.variableToStoreDeviceID = @"deviceID";
        pref.maxAttempsToPay = 3;
        pref.shouldShowSendKeyboard = YES;
        pref.notAllowedHosts = [[NSArray alloc] init];
        
        if ([Swapkey initializeWithKey:@"swap" isDevelopment:YES andPreferences:pref])
        {
            BOOL enabled = [Swapkey enableDebugging];
        }
    }
    
    self.swapkeyController = [[SwapkeyController alloc] initWithHandler:self];
    [self.swapkeyController view];
}

- (void)textWillChange:(id)textInput
{
}

- (void)updateViewConstraints
{
    [super updateViewConstraints];
    [self.swapkeyController updateViewConstraints];
}

- (void)textDidChange:(id)textInput
{
    [self.swapkeyController textDidChange:textInput];
}


@end

PETICIÓN DE ACCESO COMPLETO

Para que la extensión del teclado pueda tener acceso a internet, compartir información con la app contenedora se debe pedir al usuario que habilite el “Acceso Completo”, sin embargo para que esta opción le aparezca al usuario, en la configuración se debe habilitar en el .plis de la extensión del teclado:

1.- En el Project Navegator, abrir la carpeta del target del teclado

2.- Seleccionar el archivo Info.plis

3.- Abrir el renglón NSExtension

4.- Abrir el renglón NSExtensionAttributes

5.- Cambiar el valor del renglón RequestsOpenAccess a YES

AUTORIZANDO FACE ID

Se deberá agregar el row: "Privacy - Face ID Usage Description" al archivo .plist de la aplicación, tanto de la aplicación principal como al target del teclado, con el valor del string que explique para que se necesita el Face ID

AGREGANDO EXTENSIÓN DE iMESSAGE

Para agregar la nueva extensión se debe ir a la sección Project Navegator, seleccionar el nombre del proyecto y en la sección "Targets" dar click en el botón "+" como señala imagen a continuación:

Aparecerá una nueva ventana, se debe seleccionar iOS en la parte superior, en la sección Application Extension, se deberá buscar y dar click en "iMessage Extension" y a continuación dar click en el botón "Next".

En la siguiente ventana se deberá ingresar el nombre del Target, el lenguaje el proyecto y se deberá seleccionar en "Embed in Application" la opción del proyecto principal, como se muestra en la siguiente imagen:

Puede aparecer un venta preguntando si se desea activar el esquema, se deberá dar click en "Activate" como lo muestra la imagen:

Al realizar lo anterior, aparecerá en la parte de Project Navegator una nueva carpeta con el nombre del target recien creado, dentro de esa carpeta se encuentra el código fuente para la extensión de iMessage:

Con lo anterior se tiene un hello world de la nueva extensión, se puede compilar y aparecerá un label con el texto "Hello World"

ACTUALIZANDO EL POD

A continuación de deberá modificar el pod para que el nuevo target de iMessage Extention, tenga acceso al SDK y de igual manera se actualizará a la última versión disponible

Antes de actualizar el pod, se deberá asegurar que los targes que tendrán acceso al pod, tenga la versión 5 de Swift, que el valor de development targe sea iOS 11

Primero se deberá modificar el archivo Podfile, para que el nuevo Target, tenga acceso al pod, los nombre se deberán reemplazar por los del proyecto que se esté actualizando, así como indicar que la plataforma es ios 11:

platform :ios, '11.0'
use_frameworks!

def swap_pods
	pod 'SwapkeyExtensionSDK'
end

target 'Demo' do
    swap_pods
end

target 'DemoKeyboard' do
    swap_pods
end

target 'DemoiMessage' do
    swap_pods
end

Para continuar se deberá abrir una consola y ubicarse donde se encuentre el archivo podfile del proyecto, una vez ahí se deberá actualizar el pod con el comando update

pod update

Deberá aparecer la versión actual (señalada en la parte superior del tutorial) como actualización del pod

Se deberá ir al archivo "MainInferface.storyboard" ubicado en el target del la extensión de iMessage, se mostrará un viewcontroller con un label de texto "Hello World", se deberá eliminar este label

En el mismo targe se encuentra el archivo "MessagesViewController.h", a este se le deberá agregar el importe del SDK y el forward declaration de la clase Swapkey, quedando de la siguiente manera:

#import <Messages/Messages.h>
#import <SwapkeyExtensionSDK/SwapkeyExtensionSDK-Swift.h>

@class Swapkey;

@interface MessagesViewController : MSMessagesAppViewController

@end
		

En el archivo "MessagesViewController.m" se deberá agregar la propiedad "handler" que se encargará de controllar la clase en su mayor proporción, está deberá de ir dentro de la interface, como se muestra

@interface MessagesViewController ()
@property (nonatomic, strong) SwapkeyMessagesMain *handler;
@end

En la misma clase, dentro de la función "viewDidLoad" se deberá inicializar el SDK, junto con sus preferencias, así como instanciar el objeto "handler" como se muestra a continuación:

- (void)viewDidLoad {
	[super viewDidLoad];

	SKEPreferences *pref = [SKEPreferences getCurrentPreferences];
	if (pref != nil)
	{
		pref.bundleGroup = @"group.SKE.Test";
		pref.selfUrlToOpen = @"swap://";
		pref.variableToStoreDeviceID = @"deviceID";
		pref.maxAttempsToPay = 3;
		pref.shouldShowSendKeyboard = YES;
		pref.notAllowedHosts = [[NSArray alloc] init];
		
		if ([Swapkey initializeWithKey:@"swap" isDevelopment:YES andPreferences:pref])
		{
			BOOL enabled = [Swapkey enableDebugging];
		}
	}
	self.handler = [[SwapkeyMessagesMain alloc] initWithHandler:self];
}

Cabe señalar que las preferencia con las que se inicialice el SDK en la extensión iMessage y en la extensión Custom Keyboard, deberán ser exactamente las mismas ya que se podrían sobre escribir cuándo se abre el teclado o la aplicacion de iMessage.

Por último, se deberá implementar 4 funciones como se muestra a continuación:

-(void)willBecomeActiveWithConversation:(MSConversation *)conversation {
	[self.handler skWillBecomeActive];
}

-(void)didBecomeActiveWithConversation:(MSConversation *)conversation {
	[self.handler skDidBecomeActive];
}

-(void)willTransitionToPresentationStyle:(MSMessagesAppPresentationStyle)presentationStyle {
	[self.handler skWillTransitionTo:presentationStyle];
}

-(void)didTransitionToPresentationStyle:(MSMessagesAppPresentationStyle)presentationStyle {
	[self.handler skDidTransitionTo:presentationStyle];
}

HABILITANDO GRUPOS

De igual manera que se habilitó un app group para la aplicación host y la extensión del teclado, se deberá habilitar exactamente el mismo para la extensión de iMessage, de manera que puedan compartir información.

Se deberá ir a la sección de targets, seleccionar el target de iMessage y dar click en la sección "Signing & Capabilities"

Posteriormente se deberá dar click en el botón "+ Capability" ubicado en la parte superior izquierda de la ventana

Aparecerá una ventana en donde se debe seleccionar el tipo de Capability que se desea agregar, dar doble click en "App Groups"

Se cerrará la ventana y aparecerá la sección "App Groups", con los grupos que se puedan habilitar al target, se deberá seleccionar el app group que se tiene habilitado con anterioridad en la aplicación host y la extensión del teclado

AUTORIZACION CON FACE ID

Se deberá agregar al archivo "Info.plis" del target de iMessage el row para autorizar el uso de Face Id

Key:

Privacy - Face ID Usage Description

NOTA: Se deberán agrear los asset correspondientes en el target de iMessage para que se muestre el icono deseado en la barra de iMessage

COMPILAR Y LISTO!

Con lo anterior se puede compilar y correr el proyecto, se debe activar y dar acceso completo al teclado. Si se dan ambos permisos aparecerá lo siguiente:

Si el SDK encuentra algún problema aparecerá la siguiente pantalla:

Después de dar click en el botón “Enviar Dinero”, aparecerá un mensaje con el error:

Si el deviceID, no se ha almacenado o si hubo algún error al obtenerlo, aparecerá la siguiente pantalla:

ANEXO

Si no se ha habilitado un archivo Bridging-Header y configurado el proyecto para que se pueda compilar y correr con swift, se pueda hacer de la siguiente manera:

1.- Seleccionando la carpeta del target de la aplicación contenedora

2.- Click derecho y seleccionar New File

3.- Seleccionar Swift File

4.- Next

5.- Indicar cualquier nombre(Es un archivo temporal)

6.- Aparecerá una alerta

7.- Click en Create Bridging Header

Después de los pasos anteriores se puede eliminar el archivo temporal que se creó.