¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
Conoce nuestra marca.¿Buscas nuestro logo?
Aquí te dejamos una copia, pero si necesitas más opciones o quieres conocer más, visita nuestra área de marca.
Conoce nuestra marca.dev
Álvaro López de Diego 30/05/2022 Cargando comentarios…
¿Cómo podemos cohesionar nuestra página web con nuestra aplicación móvil? ¿Cómo podemos llevar a nuestros usuarios al contenido exacto que quieren ver? ¿Cómo hacemos esto teniendo en cuenta que nuestra base de usuarios utiliza múltiples versiones de iOS?
Un deep link, o enlace profundo, es un tipo de hipervínculo que contiene en sí mismo toda la información necesaria para llegar a un contenido concreto.
Este hecho tan sencillo nos aporta un gran valor frente al usuario. Con un simple clic será transportado automáticamente al contenido que queremos que vea, sin que tenga que lidiar con la labor de navegar entre las múltiples páginas de nuestro sitio web hasta llegar al mismo.
Como hemos dicho los deep links son una gran herramienta para transportar, con un simple enlace, a nuestros usuarios a un contenido concreto, pero además nos sirven para cohesionar los contenidos de nuestra página web y nuestras comunicaciones comerciales con las aplicaciones móviles que les distribuimos.
Gracias a ellos, y si el usuario toca el enlace en un dispositivo móvil teniendo nuestra aplicación instalada, somos capaces de llevarles a la sección correcta de la aplicación para que vean el contenido que hemos preparado de una forma totalmente adaptada al tamaño de pantalla que están usando en ese momento. No es la primera vez que hablamos de ellos en el blog: en este post ya os contamos cómo crear links dinámicos con Firebase Dynamic Links.
Ahora que sabemos qué son y para qué nos sirven, vamos a aprender a trabajar con ellos.
En el ecosistema iOS este tipo de enlaces se conocen como Universal Links o enlaces universales, e introducirlos en nuestras aplicaciones requiere unos sencillos pasos.
El primer paso consiste en definir el dominio asociado a la aplicación; esto no es más que la vinculación segura de nuestro dominio con nuestra aplicación.
Esta conexión nos permitirá realizar multitud de desarrollos que mejorarán la usabilidad de nuestra plataforma, consiguiendo así que nuestros usuarios tengan la mejor experiencia posible. Las opciones que nos abre esta conexión van desde guardar credenciales de forma segura, hasta enlazar nuestro contenido web con nuestra aplicación mediante deep links.
La primera parte de esta unión es acudir a la plataforma de desarrolladores de Apple y añadirle al identificador de nuestra aplicación la capacidad de tener dominios asociados.
Tras otorgar dicha capacidad al identificador de nuestra aplicación, nos dirigiremos a la sección Signing & Capabilities del proyecto Xcode de nuestra aplicación y añadiremos la capacidad Associated Domains. Una vez hecho esto, introduciremos nuestro dominio.
Al introducir el dominio debemos precederlo de la clave applinks:
la cual indicará al sistema operativo que la aplicación tiene un dominio asociado para deep links.
apple-app-site-association
En los dispositivos iOS cada vez que una aplicación es instalada, actualizada y aproximadamente una vez a la semana, comprueban si en la configuración de la misma hay definido algún dominio asociado. Si lo hay, realizan una petición a dicho dominio en busca de un fichero concreto, el fichero apple-app-site-association
.
La petición en cuestión es enviada contra la URL https://domain.tld/.well-known/apple-app-site-association
; analizando la dirección podemos extraer los primeros requisitos:
https
por lo que, además del servidor, necesitamos tener un certificado SSL válido..well-known
en la raíz del servidor.Además de los requisitos extraídos del análisis de la URL, también es necesario cumplir:
A continuación podemos ver un ejemplo de la estructura del fichero:
{
"applinks": {
"details": [
{
"appIDs": [
"ABCDE12345.es.ejemplo.aplicacion"
],
"components": [
{
"/": "/ejemplo/privado",
"exclude": true,
"comment": "¡No puedes pasar!"
},
{
"/": "/ejemplo/conparametros",
"?": {
"parametro1": "?????"
},
"comment": "¡Puedes pasar!"
},
{
"/": "/ejemplo/*",
"comment": "Mi comentario"
}
]
}
]
}
}
Cómo se puede apreciar, el JSON consta de una estructura y claves concretas, siendo las más importantes:
*
.query
que deben acompañar a la ruta para que la regla se cumpla. La clave del diccionario hace referencia al nombre del parámetro query
, el valor de cada clave sirve para identificar qué valores podrán llegar en el deep link.true
los enlaces que coincidan con la regla se ignorarán y no abrirán la aplicación. Su valor por defecto es false
.Además de las claves que acabamos de comentar, existen otras que también nos pueden ser útiles en alguna situación.
*
.true
.true
.A fin de aclarar lo más posible la definición de las reglas, hay que tener en cuenta:
*
para cero o más caracteres y ?
para un carácter.Nota: En lo que concierne a este artículo, únicamente hemos tratado la parte relativa a los deep links pero quiero comentar que este mismo fichero es el que se usa para definir el uso de los servicios Shared Web Credential (almacenaje de credenciales web) y el servicio de App Clips (pequeña parte de una aplicación que se usa para una tarea concreta y que no exige la instalación de la aplicación entera).
Una vez definida la configuración de la aplicación y creado el fichero apple-app-site-association
queda realizar el último paso: debemos capturar y tratar los deep links para poder navegar dentro de nuestra aplicación.
En este paso es donde entra en juego la programación. Ahora es cuando crearemos nuestro algoritmo de análisis de los deep links de manera que podamos navegar adecuadamente y llevar al usuario al contenido que desea ver. Cuando la aplicación se abre, el sistema operativo llama al método scene(_:continue:)
del UISceneDelegate. Una vez entremos en dicha función podremos acceder a la propiedad webpageURL
del parámetro userActivity
para obtener el enlace que ha ocasionado la apertura de la aplicación, analizarlo y realizar la navegación adecuada.
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
print(“===>> \(#function)")
guard let url = userActivity.webpageURL?.absoluteURL else {
return
}
print("===>> Deep Link que ha abierto la aplicación: \(url)”)
// TODO: Implementar algoritmo de decisión
}
Nota: En lo que concierne a este artículo, únicamente tratamos como capturar el deep link que ha ocasionado la apertura de la aplicación. Para analizar el enlace y ejecutar la navegación hasta el contenido dentro de la aplicación existen múltiples maneras y todas ellas dependen de la aplicación en concreto, la arquitectura implementada, etc., debido a esos factores, el análisis y navegación no se cubren en este artículo.
Todo lo que hemos descrito hasta ahora está totalmente actualizado a iOS 15 (la versión vigente cuando hemos escrito este post), pero hay un detalle que se introdujo en iOS 14 que no hemos comentado.
Anteriormente, explicábamos que el sistema operativo iOS, realiza una comprobación en la configuración de cada aplicación en busca de dominios asociados a la misma, para en caso de encontrarlos, proceder con la descarga del fichero apple-app-site-association
. Si bien esto es cierto, tenemos que tener en cuenta que la descarga de dicho fichero en iOS 14 y versiones posteriores se realiza desde el CDN (Content Delivery Network) de Apple, siendo el CDN el encargado capturar la versión más reciente del fichero apple-app-site-association
. La captura de la versión más actualizada del fichero por parte del CDN se realiza de manera recurrente cada 24 horas aproximadamente.
Este funcionamiento no debería suponer ningún tipo de problema para las aplicaciones en producción, ya que lo más habitual es que los servidores, a los que dichas aplicaciones atacan, suelen ser accesibles desde cualquier parte del mundo y, por tanto, las peticiones del CDN de Apple llegarán sin ningún problema. Sin embargo, es habitual que además del entorno de producción tengamos el de preproducción y/o desarrollo. En ellos iremos realizando cambios, añadiendo funcionalidades y preparando nuevas versiones y es por ello que, normalmente, el acceso a estos entornos está limitado a un conjunto definido de direcciones IP. En efecto, si el acceso está limitado, el CDN de Apple no podrá recuperar la versión más moderna del fichero de estos entornos preproductivos y, por ende, se nos complica la labor de desarrollo y las pruebas de nuevos deep links que queramos incluir en nuestra aplicación.
Este inconveniente tiene una solución muy sencilla de aplicar. Recordaremos que hemos tenido que añadir el dominio asociado a la configuración de nuestro proyecto Xcode; pues la solución está ahí. Debemos añadir nuevamente el dominio pero esta vez añadiéndole al final ?mode=developer
.
Al añadir este parámetro query
informamos al sistema operativo iOS que no queremos acudir al CDN a recuperar el fichero apple-app-site-association
y que, por el contrario, queremos que la petición se realice directamente contra nuestro servidor. Añadiendo esta simple query
al dominio solventamos el problema de la descarga del fichero en entornos preproductivos, lo que nos permitirá realizar nuestro desarrollo sin problema.
Es posible que queramos dar soporte con nuestra aplicación a usuarios que aún estén usando iOS 12 o incluso versiones anteriores. Para poder darles este soporte debemos realizar un par de tareas extra.
Con la llegada de iOS 13 se produjo un cambio en la estructura del fichero apple-app-site-association
dejando dicha estructura tal y como la hemos visto anteriormente, sin embargo, para las versiones iOS 12 y anteriores la estructura es distinta. A continuación podemos ver un ejemplo de la estructura incluyendo el soporte para iOS 12:
{
"applinks": {
"apps": [],
"details": [
{
"appIDs": [
"ABCDE12345.es.ejemplo.aplicacion"
],
"components": [
{
"/": "/ejemplo/privado",
"exclude": true,
"comment": "¡No puedes pasar!"
},
{
"/": "/ejemplo/conparametros",
"?": {
"parametro1": "?????"
},
"comment": "¡Puedes pasar!"
},
{
"/": "/ejemplo/*",
"comment": "Mi comentario"
}
],
"appID": "ABCDE12345.es.ejemplo.aplicacion",
"paths": [
"NOT /ejemplo/privado",
"/ejemplo/*"
]
}
]
}
}
Como se puede apreciar, hemos introducido una serie de claves concretas para dar soporte a los usuario de iOS 12:
De estas nuevas claves la más peculiar es la clave paths
cuyo contenido cambia bastante respecto a su homóloga components
usada a partir de iOS 13. En este caso se trata de una lista de las rutas que activarán la apertura de la aplicación. Analizando cada regla una a una y buscando que actúen igual que sus homólogas en iOS 13 vemos que:
/ejemplo/privado
abra la aplicación, deberemos anteponer la palabra NOT
a la ruta./ejemplo/conparametros
no ha sido incluida ya que para iOS 12 y anteriores no es posible definir reglas basadas en los parámetros query
. Este tratamiento deberemos hacerlo en la propia aplicación./ejemplo/*
se mantiene exactamente igual.*
como ?
actúan también como comodines.Con iOS 13 llegaron las escenas y apareció el UISceneDelegate
. Anteriormente hemos visto que cuando la aplicación es abierta desde un deep link el sistema llama a un método delegado, el cual nos permite capturar el enlace que ha propiciado tal apertura y realizar decisiones basadas en el análisis del mismo, pero ¿cómo haremos esto en iOS 12?
En iOS 12 y anteriores versiones podemos usar el UIAppDelegate, en concreto el método delegado application(_:continue:restorationHandler:)
que será llamado cuando la aplicación se abra desde un deep link. Al igual que en el homólogo del UISceneDelegate
, podremos acceder a la propiedad webpageURL
del parámetro userActivity
para obtener el enlace que ha ocasionado la apertura de la aplicación, analizarlo y realizar la navegación adecuada.
func application(_ app: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
print("===>> \(#function)")
guard let url = userActivity.webpageURL?.absoluteURL else {
return false
}
print("===>> DeepLink que ha abierto la aplicación: \(url)")
// TODO: Implementar algoritmo de decisión
return true
}
Nota: Al igual que en la sección anterior, únicamente tratamos como capturar el deep link que ha ocasionado la apertura de la aplicación. El análisis y navegación no se cubren en este artículo.
Es bastante habitual que usemos los simuladores para probar nuestra aplicación, comprobar que el código que programamos hace lo que esperamos y que todo funciona de forma correcta. Lógicamente, querremos probar el algoritmo de análisis y navegación que hemos diseñado para tratar los deep links que abran nuestra aplicación. Para ello, se nos puede ocurrir que lo más sencillo es instalar la aplicación en el simulador, ir a Safari, pegar el enlace y… desgraciadamente este método no funciona; el enlace se cargará en el navegador y la aplicación no se abrirá. Esto se debe a que en iOS los enlaces que desencadenan la comprobación de reglas de los deep links deben ser pulsados.
Una vez que sabemos esto, se nos puede ocurrir que una forma de hacerlo es ir a la aplicación Mensajes del simulador, pegar el enlace, enviarlo a la conversación y después hacer clic sobre él para iniciar todo el proceso. En efecto, este proceso funcionará pero es extremadamente laborioso y, por suerte, hay otra forma de hacerlo. Para ello solo necesitamos la terminal de nuestro ordenador para ejecutar xcrun simctl openurl booted $URL
. Con esa sencilla línea podremos ordenar a nuestro simulador que abra el enlace que digamos como si hubiéramos pulsado sobre él, desencadenando así todo el proceso de comprobación de reglas y posterior apertura de la aplicación. Desgranando la instrucción anterior:
simctl
que escoja uno de los simuladores encendidos para ejecutar la orden indicada, en este caso openurl
. En caso de tener varios simuladores escogerá uno al azar. Este campo se puede sustituir por el UUID del simulador que queramos usar.https://domain.tld/ejemplo/pagina1
.Con este sencillo comando podremos abrir todos los deep links que queramos en nuestros simuladores a fin de probar nuestro algoritmo de análisis y navegación.
Es posible que durante nuestro desarrollo nos encontremos en la situación de que debemos incluir el tratamiento de un nuevo deep link en nuestra aplicación. En este caso, modificaremos nuestro fichero apple-app-site-association
e implementaremos la decisión correspondiente a este nuevo enlace en nuestra aplicación. Una vez hecho esto tenemos que probarlo y para ello es necesario que subamos el fichero al servidor a fin de que iOS se lo descargue cuando instalemos la aplicación en el simulador y poder probar el nuevo deep link. En este punto aparece un conflicto; no tengo acceso a los servidores y por tanto no puedo subir el fichero actualizado.
Bien, ante esta situación tenemos una contramedida llamada Proxyman. Proxyman es una aplicación para MacOS que actúa de “proxy” del sistema que nos permite ver y manipular las peticiones http
y https
que pasan por él.
Dado que la descarga del fichero apple-app-site-association
es una petición https
podemos usar Proxyman para interceptarla y cambiar el contenido del cuerpo de la respuesta. En dicha intercepción, podemos añadir esa nueva regla que nos permita probar el nuevo deep link y su correspondiente nueva decisión incluida en el algoritmo de nuestra aplicación. Para ello utilizaremos el módulo Scripting de Proxyman que con un poco de Javascript nos permitirá modificar la respuesta.
A lo largo de todo el artículo hemos visto cómo podemos cohesionar nuestra página web con nuestra aplicación móvil, de manera que demos continuidad total a nuestros usuarios. Todo ello es gracias a los deep links. Son un gran herramienta, pero en lo que se refiere al ecosistema iOS hay que aprender a trabajar con ellos, y las claves son:
apple-app-site-association
.Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.
Cuéntanos qué te parece.