Что нового в Web In Play

Опубликовано: 2 декабря 2020 г.

С момента введения Trusted Web Activity команда Chrome упростила использование Bubblewrap. Мы добавили дополнительные функции, такие как интеграция Google Play Billing , и дали возможность работать на большем количестве платформ, таких как ChromeOS .

Функции Bubblewrap и Trusted Web Activity

Bubblewrap помогает вам создавать приложения, которые запускают ваши PWA внутри Trusted Web Activity, без необходимости знания инструментов, специфичных для платформы.

Упрощенный процесс настройки

Раньше использование Bubblewrap требовало ручной настройки Java Development Kit и Android SDK, оба из которых подвержены ошибкам. Теперь инструмент предлагает автоматически загружать внешние зависимости при первом запуске.

При желании вы по-прежнему можете использовать существующую установку зависимостей, а новая команда doctor помогает находить проблемы и рекомендует исправления конфигурации, которую теперь можно обновить из командной строки с помощью команды updateConfig .

Улучшенный мастер

При создании проекта с помощью init Bubblewrap нужна информация для генерации приложения Android. Инструмент извлекает значения из Web App Manifest и предоставляет значения по умолчанию, где это возможно.

Вы можете изменить эти значения при создании нового проекта, но ранее значение каждого поля было неясным. Диалоги инициализации были перестроены с лучшими описаниями и проверкой для каждого поля ввода.

Поддержка полноэкранного режима и ориентации дисплея

В некоторых случаях вам может потребоваться, чтобы ваше приложение использовало как можно большую часть экрана, и при создании PWA это реализуется путем установки поля display в манифесте веб-приложения на fullscreen .

Когда Bubblewrap обнаруживает опцию полноэкранного режима в манифесте веб-приложения, он настраивает приложение Android на запуск в полноэкранном режиме, или в режиме погружения , в терминах, характерных для Android.

Поле orientation из Web App Manifest определяет, должно ли приложение запускаться в портретном режиме, ландшафтном режиме или в ориентации, которую в данный момент использует устройство. Bubblewrap теперь считывает поле Web App Manifest и использует его по умолчанию при создании приложения Android.

Обе конфигурации можно настроить как часть процесса bubblewrap init .

Вывод AppBundles

App Bundles — это формат публикации приложений, который делегирует окончательную генерацию APK и подписание в Play. На практике это позволяет предоставлять пользователям файлы меньшего размера при загрузке приложения из магазина.

Bubblewrap теперь упаковывает приложение как App Bundle в файле app-release-bundle.aab . Вам следует отдать предпочтение этому формату при публикации приложений в Play Store, так как это требуется магазином с 2021 года .

Делегирование геолокации

Пользователи ожидают, что приложения, установленные на их устройствах, будут вести себя согласованно, независимо от технологии. При использовании внутри Trusted Web Activity разрешение GeoLocation теперь может быть делегировано операционной системе, и при включении пользователи видят те же диалоги, что и приложения, созданные с помощью Kotlin или Java, и находят элементы управления для управления разрешением в том же месте.

Эту функцию можно добавить через Bubblewrap, и поскольку она добавляет дополнительные зависимости в проект Android, ее следует включать только тогда, когда веб-приложение использует разрешение на геолокацию.

Оптимизированные двоичные файлы

Устройства с ограниченным хранилищем распространены в определенных регионах мира, и владельцы таких устройств часто предпочитают приложения меньшего размера. Приложения, использующие Trusted Web Activity, создают небольшие двоичные файлы, что снимает часть беспокойства у этих пользователей.

Bubblewrap был оптимизирован путем сокращения списка необходимых библиотек Android, что привело к созданию двоичных файлов, которые на 800k меньше. На практике это меньше половины среднего размера, созданного предыдущими версиями. Чтобы воспользоваться преимуществами меньших двоичных файлов, вам нужно только обновить свое приложение, используя последнюю версию Bubblewrap.

Как обновить существующее приложение

Приложение, созданное Bubblewrap, состоит из веб-приложения и облегченной оболочки Android, которая открывает PWA. Несмотря на то, что PWA, открытая внутри Trusted Web Activity, следует тем же циклам обновления, что и любое веб-приложение, собственная оболочка может и должна обновляться.

Вам следует обновить свое приложение, чтобы убедиться, что оно использует последнюю версию оболочки с последними исправлениями ошибок и функциями. При установке последней версии Bubblewrap команда update применяет последнюю версию оболочки к существующему проекту:

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

Еще одна причина обновить эти приложения — убедиться, что изменения в Web Manifest применены к приложению. Используйте для этого новую команду merge :

bubblewrap merge
bubblewrap update
bubblewrap build

Обновления критериев качества

В Chrome 86 были внесены изменения в критерии качества Trusted Web Activity, которые подробно описаны в разделе Изменения критериев качества для PWA, использующих Trusted Web Activity .

Краткое резюме: вам следует убедиться, что ваши приложения обрабатывают следующие сценарии, чтобы предотвратить их сбои:

  • Невозможность проверки ссылок на цифровые активы при запуске приложения
  • Невозможность возврата HTTP 200 для запроса автономного сетевого ресурса
  • Возврат ошибки HTTP 404 или 5xx в приложении.

Помимо обеспечения прохождения приложением проверки ссылок на цифровые активы , оставшиеся сценарии могут быть обработаны сервисным работником:

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 использует лучшие практики и удаляет шаблоны при использовании service workers. В качестве альтернативы рассмотрите возможность использования плагина Workbox для обработки таких сценариев:

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,
    });
  }
}