Novedades de Web en Play

Publicado: 2 de diciembre de 2020

Desde que se introdujo la Actividad web de confianza, el equipo de Chrome facilitó su uso con Bubblewrap. Agregamos funciones adicionales, como la integración de la Facturación Google Play, y la habilitamos para que funcione en más plataformas, como ChromeOS.

Funciones de Bubblewrap y de la Actividad web de confianza

Bubblewrap te ayuda a crear apps que inicien tus AWP dentro de una actividad web de confianza, sin necesidad de tener conocimientos de las herramientas específicas de la plataforma.

Flujo de configuración simplificado

Anteriormente, para usar Bubblewrap, se requería configurar manualmente el kit de desarrollo de Java y el SDK de Android, que son propensos a errores. La herramienta ahora ofrece descargar automáticamente las dependencias externas cuando se ejecuta por primera vez.

Si lo prefieres, puedes optar por usar una instalación existente de las dependencias, y el nuevo comando doctor ayuda a encontrar problemas y recomienda correcciones para la configuración, que ahora se puede actualizar desde la línea de comandos con el comando updateConfig.

Asistente mejorado

Cuando se crea un proyecto con init, Bubblewrap necesita información para generar la app para Android. La herramienta extrae valores del manifiesto de la app web y proporciona valores predeterminados cuando es posible.

Puedes cambiar esos valores cuando creas un proyecto nuevo, pero antes el significado de cada campo no estaba claro. Se volvieron a compilar los diálogos de inicialización con mejores descripciones y validación para cada campo de entrada.

Compatibilidad con la pantalla completa y la orientación de la pantalla

En algunos casos, es posible que quieras que tu aplicación use la mayor parte de la pantalla posible y, cuando compiles las AWP, esto se implementa configurando el campo display del manifiesto de la app web en fullscreen.

Cuando Bubblewrap detecta la opción de pantalla completa en el manifiesto de la app web, configura la aplicación para Android para que también se inicie en pantalla completa o en modo envolvente, en términos específicos de Android.

El campo orientation del manifiesto de la app web define si la aplicación debe iniciarse en modo vertical, modo horizontal o en la orientación que el dispositivo esté usando en ese momento. Bubblewrap ahora lee el campo del manifiesto de la app web y lo usa como valor predeterminado cuando crea la app para Android.

Puedes personalizar ambas opciones de configuración como parte del flujo de bubblewrap init.

Resultado de AppBundles

App Bundles es un formato de publicación para apps que delega la generación y la firma del APK final a Play. En la práctica, esto permite que se entreguen archivos más pequeños a los usuarios cuando descargan la app desde la tienda.

Bubblewrap ahora empaqueta la aplicación como un paquete de aplicación, en un archivo llamado app-release-bundle.aab. Te recomendamos que uses este formato cuando publiques apps en Play Store, ya que es obligatorio desde 2021.

Delegación de ubicación geográfica

Los usuarios esperan que las aplicaciones instaladas en sus dispositivos se comporten de manera coherente, independientemente de la tecnología. Cuando se usa dentro de una Actividad web de confianza, el permiso de GeoLocation ahora se puede delegar al sistema operativo y, cuando está habilitado, los usuarios ven los mismos diálogos que las apps compiladas con Kotlin o Java, y encuentran controles para administrar el permiso en el mismo lugar.

La función se puede agregar a través de Bubblewrap y, como agrega dependencias adicionales al proyecto de Android, solo debes habilitarla cuando la app web use el permiso de ubicación geográfica.

Objetos binarios optimizados

Los dispositivos con almacenamiento limitado son comunes en ciertas áreas del mundo, y los propietarios de esos dispositivos suelen preferir aplicaciones más pequeñas. Las aplicaciones que usan la Actividad web de confianza producen objetos binarios pequeños, lo que reduce la ansiedad de esos usuarios.

Bubblewrap se optimizó reduciendo la lista de bibliotecas de Android necesarias, lo que dio como resultado binarios generados que son 800 KB más pequeños. En la práctica, eso es menos de la mitad del tamaño promedio que generaban las versiones anteriores. Para aprovechar los objetos binarios más pequeños, solo debes actualizar tu app con la versión más reciente de Bubblewrap.

Cómo actualizar una app existente

Una aplicación generada por Bubblewrap se compone de una aplicación web y un wrapper ligero de Android que abre la AWP. Aunque la AWP que se abre dentro de una actividad web de confianza sigue los mismos ciclos de actualización que cualquier app web, el wrapper nativo puede y debe actualizarse.

Debes actualizar tu app para asegurarte de que use la versión más reciente del wrapper, con las funciones y correcciones de errores más recientes. Con la versión más reciente de Bubblewrap instalada, el comando update aplica la versión más reciente del wrapper a un proyecto existente:

npm update -g @bubblewrap/cli
bubblewrap update
bubblewrap build

Otro motivo para actualizar esas aplicaciones es garantizar que se apliquen los cambios en el manifiesto web. Usa el nuevo comando merge para eso:

bubblewrap merge
bubblewrap update
bubblewrap build

Actualizaciones de los criterios de calidad

En Chrome 86, se introdujeron cambios en los criterios de calidad de las actividades web de confianza, que se explican en detalle en Cambios en los criterios de calidad de las AWP que usan actividades web de confianza.

En resumen, debes asegurarte de que tus aplicaciones controlen las siguientes situaciones para evitar que fallen:

  • No se verificaron los vínculos de recursos digitales en el lanzamiento de la aplicación
  • No se devuelve el código HTTP 200 para una solicitud de recurso de red sin conexión
  • Devolución de un error HTTP 404 o 5xx en la aplicación

Además de garantizar que la aplicación apruebe la validación de Vínculos de recursos digitales, un service worker puede controlar las situaciones restantes:

self.addEventListener('fetch', event => {
  event.respondWith((async () => {
    try {
      return await fetchAndHandleError(event.request);
    } catch {
      // Failed to load from the network. User is offline or the response
      // has a status code that triggers the Quality Criteria.
      // Try loading from cache.
      const cachedResponse = await caches.match(event.request);
      if (cachedResponse) {
        return cachedResponse;
      }
      // Response was not found on the cache. Send the error / offline
      // page. OFFLINE_PAGE should be pre-cached when the service worker
      // is activated.
      return await caches.match(OFFLINE_PAGE);
    }
  })());
});

async function fetchAndHandleError(request) {
  const cache = await caches.open(RUNTIME_CACHE);
  const response = await fetch(request);

  // Throw an error if the response returns one of the status
  // that trigger the Quality Criteria.
  if (response.status === 404 ||
      response.status >= 500 && response.status < 600) {
    throw new Error(`Server responded with status: ${response.status}`);
  }

  // Cache the response if the request is successful.
  cache.put(request, response.clone());
  return response;
}

Workbox incorpora prácticas recomendadas y quita el código estándar cuando se usan service workers. Como alternativa, considera usar un complemento de Workbox para controlar esas situaciones:

export class FallbackOnErrorPlugin {
  constructor(offlineFallbackUrl, notFoundFallbackUrl, serverErrorFallbackUrl) {
    this.notFoundFallbackUrl = notFoundFallbackUrl;
    this.offlineFallbackUrl = offlineFallbackUrl;
    this.serverErrorFallbackUrl = serverErrorFallbackUrl;
  }

  checkTrustedWebActivityCrash(response) {
    if (response.status === 404 || response.status >= 500 && response.status <= 600) {
      const type = response.status === 404 ? 'E_NOT_FOUND' : 'E_SERVER_ERROR';
      const error = new Error(`Invalid response status (${response.status})`);
      error.type = type;
      throw error;
    }
  }

  // This is called whenever there's a network response,
  // but we want special behavior for 404 and 5**.
  fetchDidSucceed({response}) {
    // Cause a crash if this is a Trusted Web Activity crash.
    this.checkTrustedWebActivityCrash(response);

    // If it's a good response, it can be used as-is.
    return response;
  }

  // This callback is new in Workbox v6, and is triggered whenever
  // an error (including a NetworkError) is thrown when a handler runs.
  handlerDidError(details) {
    let fallbackURL;
    switch (details.error.details.error.type) {
      case 'E_NOT_FOUND': fallbackURL = this.notFoundFallbackUrl; break;
      case 'E_SERVER_ERROR': fallbackURL = this.serverErrorFallbackUrl; break;
      default: fallbackURL = this.offlineFallbackUrl;
    }

    return caches.match(fallbackURL, {
      // Use ignoreSearch as a shortcut to work with precached URLs
      // that have _WB_REVISION parameters.
      ignoreSearch: true,
    });
  }
}