Integración en el SO

Las aplicaciones web tienen un gran alcance. Se ejecutan en varias plataformas. Se pueden compartir fácilmente a través de vínculos. Sin embargo, tradicionalmente, no tenían integración con el sistema operativo. Hace poco, ni siquiera se podían instalar. Afortunadamente, eso cambió y ahora podemos aprovechar esa integración para agregar funciones útiles a nuestras AWP. Analicemos algunas de esas opciones.

Cómo trabajar con el sistema de archivos

Un flujo de trabajo típico del usuario que usa archivos se ve así:

  • Elige un archivo o una carpeta del dispositivo y ábrelo directamente.
  • Realiza cambios en esos archivos o carpetas y guárdalos directamente.
  • Crear archivos y carpetas nuevos

Antes de la API de File System Access, las apps web no podían hacer esto. Para abrir archivos, se debía subir un archivo, y para guardar los cambios, los usuarios debían descargarlos. Además, la Web no tenía acceso para crear archivos y carpetas nuevos en el sistema de archivos del usuario.

Abrir un archivo

Para abrir un archivo, usamos el método window.showOpenFilePicker(). Ten en cuenta que este método requiere un gesto del usuario, como hacer clic en un botón. Este es el resto de la configuración para abrir un archivo:

  1. Captura el control de archivo de la API del selector de archivos del acceso al sistema de archivos. Esto te brinda información básica sobre el archivo.
  2. Con el método getFile() del controlador, obtendrás un tipo especial de Blob llamado File que incluye propiedades adicionales de solo lectura (como el nombre y la fecha de la última modificación) sobre el archivo. Como es un BLOB, se pueden llamar a sus métodos, como text(), para obtener su contenido.
// Have the user select a file.
const [ handle ] = await window.showOpenFilePicker();
// Get the File object from the handle.
const file = await handle.getFile();
// Get the file content.
// Also available, slice(), stream(), arrayBuffer()
const content = await file.text();

Guardando los cambios

Para guardar los cambios en un archivo, también necesitas un gesto del usuario. Luego, haz lo siguiente:

  1. Usa el identificador de archivo para crear un FileSystemWritableFileStream.
  2. Realiza cambios en el flujo. Esto no actualizará el archivo en su lugar. En su lugar, se suele crear un archivo temporal.
  3. Por último, cuando termines de realizar los cambios, cierra la transmisión, lo que hará que los cambios pasen de ser temporales a permanentes.

Veamos esto en el código:

// Make a writable stream from the handle.
const writable = await handle.createWritable();
// Write the contents of the file to the stream.
await writable.write(contents);
// Close the file and write the contents to disk.
await writable.close();

Manejo de archivos

La API de File System Access te permite abrir archivos desde tu app, pero ¿qué sucede al revés? Los usuarios quieren establecer su app favorita como la predeterminada para abrir archivos. La API de control de archivos es una API experimental que permite que las AWP instaladas hagan lo siguiente: Registrarse como controlador de archivos en el dispositivo de un usuario y especificar el tipo MIME y la extensión de archivo que admite tu AWP en el manifiesto de la app web. Puedes especificar íconos de archivos personalizados para tus extensiones compatibles.

Una vez registrada, la AWP instalada aparecerá como una opción en el sistema de archivos del usuario, lo que le permitirá abrir el archivo directamente en ella. A continuación, se muestra un ejemplo de la configuración del manifiesto para que una AWP lea archivos de texto:

...
"file_handlers": [
     {
         "action": "/open-file",
         "accept": {
             "text/*": [".txt"]
         }
     }
]
...

Manejo de URLs

Con el manejo de URLs, tu AWP puede capturar vínculos que forman parte de su alcance desde el sistema operativo y renderizarlos en una ventana de la AWP, en lugar de la pestaña predeterminada del navegador. Por ejemplo, si recibes un mensaje que vincula a la AWP o haces clic en un vínculo directo (una URL que dirige a un contenido específico) en la AWP, el contenido se abrirá en una ventana independiente.

Este comportamiento está disponible automáticamente en Android cuando se usa WebAPK, por ejemplo, cuando los usuarios instalan una AWP con Chrome. Es imposible capturar URLs en las AWP instaladas en iOS y iPadOS desde Safari.

En el caso de los navegadores para computadoras, la comunidad de navegadores web creó una especificación nueva. Actualmente, esta especificación es experimental y agrega un nuevo miembro de archivo de manifiesto: url_handlers. Esta propiedad espera un array de orígenes que la AWP desea capturar. El origen de tu AWP se otorgará automáticamente, y todos los demás orígenes deben aceptar ese manejo que opera a través de un archivo llamado web-app-origin-association. Por ejemplo, si el manifiesto de tu AWP se aloja en web.dev y deseas agregar el origen app.web.dev, se vería de la siguiente manera:

"url_handlers": [
    {"origin": "https://app.web.dev"},
]

En este caso, el navegador verificará si existe un archivo en app.web.dev/.well-known/web-app-origin-association y aceptará el manejo de URL de la URL de alcance de la AWP. El desarrollador debe crear este archivo. En el siguiente ejemplo, el archivo se ve de la siguiente manera:

{
    "web_apps": [
        {
            "manifest": "/mypwa/app.webmanifest",
            "details": {
                "paths": [ "/*" ]
            }
        }
    ]
}

Manejo de protocolos de URL

El manejo de URLs funciona con URLs de protocolo https estándar, pero es posible usar esquemas de URI personalizados, como pwa://. En varios sistemas operativos, las apps instaladas obtienen esta capacidad cuando registran sus esquemas.

En el caso de las AWP, esta función se habilita con la API del controlador de protocolo de URL, que solo está disponible en dispositivos de escritorio. Solo puedes permitir protocolos personalizados para dispositivos móviles si distribuyes tu AWP en tiendas de aplicaciones.

Para registrarte, puedes usar el método registerProtocolHandler() o el miembro protocol_handlers en tu manifiesto, con el esquema deseado y la URL que deseas cargar en el contexto de tu PWA, como:

...
{
  "protocol_handlers": [
    {
      "protocol": "web+pwa",
      "url": "/from-protocol?value=%s"
    },
  ]
}
...

Puedes enrutar la URL from-protocol al controlador correcto y obtener la cadena de consulta value en tu AWP. %s es un marcador de posición para la URL escapada que activó la operación, por lo que, si tienes un vínculo en algún lugar, como <a href="web+pwa://testing">, tu AWP abrirá /from-protocol?value=testing.

Cómo llamar a otras apps

Puedes usar esquemas de URI para conectarte a cualquier otra app instalada (PWA o no) en los dispositivos de los usuarios en todas las plataformas. Solo debes crear un vínculo o usar navigator.href y dirigirte al esquema de URI que deseas. Para ello, pasa los argumentos en formato de URL con escape.

Puedes usar esquemas estándar conocidos, como tel: para llamadas telefónicas, mailto: para el envío de correos electrónicos o sms: para mensajes de texto, o bien puedes obtener información sobre otros esquemas de URL de apps, por ejemplo, de aplicaciones de mensajería, mapas, navegación, reuniones en línea, redes sociales y tiendas de aplicaciones conocidas.

Uso compartido en la Web

Browser Support

  • Chrome: 89.
  • Edge: 93.
  • Firefox: behind a flag.
  • Safari: 12.1.

Source

Con la API de Web Share, tu AWP puede enviar contenido a otras apps instaladas en el dispositivo a través del canal compartido.

La API solo está disponible en sistemas operativos con un mecanismo share, incluidos Android, iOS, iPadOS, Windows y ChromeOS. Puedes compartir un objeto que contenga lo siguiente:

  • Texto (propiedades title y text)
  • Una URL (propiedad url)
  • Archivos (propiedad files)

Para verificar si el dispositivo actual puede compartir datos simples, como texto, verifica la presencia del método navigator.share(). Para compartir archivos, verifica la presencia del método navigator.canShare().

Para solicitar la acción de compartir, llama a navigator.share(objectToShare). Esa llamada muestra una promesa que se resuelve con undefined o se rechaza con una excepción.

Chrome en Android y Safari en iOS abren la hoja compartida gracias a Compartir con la Web.

Web Share Target

La API de Web Share Target permite que tu AWP sea el objetivo de una operación de uso compartido desde otra app en ese dispositivo, ya sea una AWP o no. Tu AWP recibe los datos que comparte otra app.

Actualmente, está disponible en Android con WebAPK y ChromeOS, y solo funciona después de que el usuario instala tu AWP. El navegador registra el destino de uso compartido dentro del sistema operativo cuando se instala la app.

Configuras el objetivo de uso compartido web en el manifiesto con el miembro share_target definido en la especificación de borrador del objetivo de uso compartido web. share_target se establece en un objeto con algunas propiedades:

action
URL que se cargará en una ventana de la AWP que se espera que reciba los datos compartidos.
method
Se usará el método de verbo HTTP
para la acción, como GET, POST o PUT.
enctype
(Opcional) El tipo de codificación para los parámetros es application/x-www-form-urlencoded de forma predeterminada, pero también se puede establecer como multipart/form-data para métodos como POST.
params
Un objeto que asignará datos de uso compartido (de las claves: title, text, url y files de Compartir con la Web) a argumentos que el navegador pasará en la URL (en method: 'GET') o en el cuerpo de la solicitud con la codificación seleccionada.

Por ejemplo, puedes definir para tu AWP que deseas recibir datos compartidos (solo el título y la URL) agregando lo siguiente a tu manifiesto:

...
"share_target": {
   "action": "/receive-share/",
   "method": "GET",
   "params": {
      "title": "shared_title",
      "url": "shared_url"
   }
}
...

En el ejemplo anterior, si alguna app del sistema comparte una URL con un título y el usuario elige tu AWP desde el diálogo, el navegador creará una nueva navegación al /receive-share/?shared_title=AAA&shared_url=BBB de tu origen, donde AAA es el título compartido y BBB es la URL compartida. Puedes usar JavaScript para leer esos datos de la cadena window.location si la analizas con el constructor URL.

El navegador usará el nombre y el ícono de la AWP de tu manifiesto para alimentar la entrada de uso compartido del sistema operativo. No puedes elegir un conjunto diferente para ese propósito.

Para obtener ejemplos más detallados y cómo recibir archivos, consulta Cómo recibir datos compartidos con la API de Web Share Target.

Seleccionador de contactos

Browser Support

  • Chrome: not supported.
  • Edge: not supported.
  • Firefox: not supported.
  • Safari: not supported.

Source

Con la API de Contact Picker, puedes solicitar que el dispositivo renderice un diálogo nativo con todos los contactos del usuario para que pueda elegir uno o más. Luego, tu AWP puede recibir los datos que desees de esos contactos.

La API de Contact Picker está disponible principalmente en dispositivos móviles, y todo se realiza a través de la interfaz navigator.contacts en plataformas compatibles.

Puedes solicitar las propiedades disponibles para consultar con navigator.contacts.getProperties() y solicitar una selección de contactos única o múltiple con una lista de las propiedades deseadas.

Algunas propiedades de muestra son name, email, address y tel. Cuando le pidas al usuario que elija uno o más contactos, puedes llamar a navigator.contacts.select(properties) y pasar un array de propiedades que deseas obtener a cambio.

En el siguiente ejemplo, se mostrarán los contactos que recibió el selector.

async function getContacts() {
   const properties = ['name', 'email', 'tel'];
   const options = { multiple: true };
   try {
     const contacts = await navigator.contacts.select(properties, options);
     console.log(contacts);
   } catch (ex) {
     // Handle any errors here.
   }
}

Recursos