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

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

Новые функции Bubblewrap и Trusted Web Activity.

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

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

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

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

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

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

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

дисплей: полноэкранный режим и поддержка ориентации

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

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

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

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

Вывод AppBundles

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

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

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

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

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

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

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

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

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

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

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

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

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

bubblewrap merge
bubblewrap update
bubblewrap build

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

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

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

  • Невозможность проверки ссылок на цифровые активы при запуске приложения.
  • Невозможность возврата 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 выполняет запекание в соответствии с лучшими практиками и удаляет шаблоны при использовании сервис-воркеров. В качестве альтернативы рассмотрите возможность использования плагина 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,
    });
  }
}

Оплата Google Play

Помимо того, что ваше приложение позволяет вашему приложению продавать цифровые товары и подписки в Play Store, Google Play Billing предлагает инструменты для управления вашим каталогом, ценами и подписками, полезные отчеты и процесс оформления заказа на базе Play Store, который уже знаком вашим пользователям. Это также требование для приложений, опубликованных в Play Store и продающих цифровые товары.

Chrome 88 будет выпущен с пробной версией Origin на Android, которая позволит интегрировать Trusted Web Activity , API запросов платежей и API цифровых товаров для реализации потоков покупок через выставление счетов в Google Play. Мы ожидаем, что пробная версия Origin также будет доступна для ChromeOS версии 89.

Важно! API биллинга Google Play имеет собственную терминологию и включает клиентские и серверные компоненты. В этом разделе рассматривается лишь небольшая часть API, предназначенная для использования API цифровых товаров и доверенной веб-активности. Обязательно прочтите документацию по биллингу Google Play и разберитесь в ее концепциях, прежде чем интегрировать ее в рабочее приложение.

Основной поток

Меню игровой консоли

Чтобы предоставлять цифровые товары через Play Store, вам необходимо настроить свой каталог в Play Store, а также подключить Play Store в качестве способа оплаты из вашего PWA.

Когда вы будете готовы настроить свой каталог, начните с поиска раздела «Продукты» в левом меню Play Console:

Здесь вы найдете возможность просмотреть существующие продукты и подписки в приложении, а также кнопку «Создать» для добавления новых.

Продукты внутри приложения

информация о продукте

Чтобы создать новый продукт для продажи в приложении, вам понадобится идентификатор продукта, название, описание и цена. Важно создать осмысленные и легко запоминающиеся идентификаторы продуктов. Они понадобятся вам позже, и после создания идентификаторы нельзя будет изменить.

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

После создания каждого продукта сделайте его доступным из вашего приложения, активировав его.

Если вы предпочитаете, вы можете добавлять свои продукты через Play Developers API .

После настройки каталога следующим шагом будет настройка потока оформления заказа из PWA. Для достижения этой цели вы будете использовать комбинацию API цифровых товаров и API запроса платежа .

Получите цену продукта с помощью API цифровых товаров

При использовании Google Play Billing вам необходимо убедиться, что цена, отображаемая пользователям, соответствует цене, указанной в списке магазинов. Синхронизировать эти цены вручную было бы невозможно, поэтому API цифровых товаров предоставляет веб-приложению возможность запрашивать цены у основного поставщика платежей:

// The SKU for the product, as defined in the Play Store interface
async function populatePrice(sku) {
  try {
    // Check if the Digital Goods API is supported by the browser.
    if (window.getDigitalGoodsService) {
      // The Digital Goods API can be supported by other Payments provider.
      // In this case, we're retrieving the Google Play Billing provider.
      const service =
          await window.getDigitalGoodsService("https://play.google.com/billing");

      // Fetch product details using the `getDetails()` method.
      const details = await service.getDetails([sku]);

      if (details.length === 0) {
        console.log(`Could not get SKU: "${sku}".`);
        return false;
      }

      // The details will contain both the price and the currenncy.
      item = details[0];
      const value = item.price.value;
      const currency = item.price.currency;

      const formattedPrice = new Intl.NumberFormat(navigator.language, {
        style: 'currency', currency: currency }).format(value);

      // Display the price to the user.
      document.getElementById("price").innerHTML = formattedPrice;
    } else {
      console.error("Could not get price for SKU \"" + sku + "\".");
    }
  } catch (error) {
    console.log(error);
  }
  return false;
}

Вы можете обнаружить поддержку API цифровых товаров, проверив, доступен ли getDigitalGoodsService() для объекта window .

Затем вызовите window.getDigitalGoodsService() , указав в качестве параметра платежный идентификатор Google Play. Это вернет экземпляр службы для Google Play Billing, а другие поставщики смогут реализовать поддержку API цифровых товаров и будут иметь другие идентификаторы.

Наконец, вызовите getDetails() по ссылке на объект Google Play Billing, передав SKU для элемента в качестве параметра. Метод вернет объект сведений, содержащий цену и валюту товара, который может быть отображен пользователю.

Запустите процесс покупки

API запроса платежа обеспечивает потоки покупок в Интернете, а также используется для интеграции биллинга Google Play. Ознакомьтесь с статьей «Как работает API запросов платежей», чтобы узнать больше, если вы новичок в API запросов платежей.

Чтобы использовать API с биллингом Google Play, вам необходимо добавить платежный инструмент, поддерживающий метод https://play.google.com/billing , и добавить SKU как часть данных для инструмента:

const supportedInstruments = [{
  supportedMethods: "https://play.google.com/billing",
  data: {
    sku: sku
  }
}];

Затем создайте объект PaymentRequest как обычно и используйте API как обычно.

const request = new PaymentRequest(supportedInstruments, details);

Подтвердить покупку

После завершения транзакции вам нужно будет использовать API цифровых товаров для подтверждения платежа. Объект ответа из PaymentRequest будет содержать токен, который вы будете использовать для подтверждения транзакции:

const response = await request.show();
const token = response.details.token;
const service =
          await window.getDigitalGoodsService("https://play.google.com/billing");
await service.acknowledge(token, 'onetime');

API цифровых товаров и API запросов платежей не имеют информации о личности пользователя. В результате вы должны связать покупку с пользователем в своем бэкэнде и обеспечить ему доступ к приобретенным товарам. Привязывая покупку к пользователю, не забудьте сохранить токен покупки, так как он может понадобиться вам, чтобы проверить, была ли покупка отменена или возмещена, или активна ли подписка. Ознакомьтесь с API уведомлений разработчика в реальном времени и API разработчика Google Play , поскольку они предоставляют конечные точки для обработки этих случаев в вашем бэкэнде.

Проверьте существующие права

Возможно, пользователь активировал промокод или уже имеет подписку на ваш продукт. Чтобы проверить наличие у пользователя соответствующих прав, вы можете вызвать команду listPurchases() в сервисе цифровых товаров. Это вернет все покупки, которые ваш клиент совершил в вашем приложении. Здесь также можно будет подтвердить любые неподтвержденные покупки, чтобы гарантировать, что пользователь правильно воспользуется своими правами.

const purchases = await itemService.listPurchases();
for (p of purchases) {
  if (!p.acknowledged) {
    await itemService.acknowledge(p.purchaseToken, 'onetime');
  }
}

Загрузите в магазин ChromeOS Play.

Доверенные веб-действия также доступны начиная с Chrome 85 в ChromeOS Play Store. Процесс размещения вашего приложения в магазине для ChromeOS такой же, как и для Android.

После того как вы создали пакет приложений, Play Console проведет вас через необходимые шаги для размещения приложения в Play Store. В документации Play Console вы можете найти помощь по созданию списка приложений , управлению APK-файлами и другими настройками, а также инструкции по тестированию и безопасному выпуску вашего приложения .

Чтобы ограничить использование вашего приложения только Chromebook, добавьте флаг --chromeosonly при инициализации приложения в Bubblewrap:

bubblewrap init --manifest="https://example.com/manifest.json" --chromeosonly

При создании приложения вручную, без Bubblewrap, добавьте флаг uses-feature в манифест Android:

<uses-feature  android:name="org.chromium.arc" android:required="true"/>

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