Co nowego w aplikacjach internetowych w Google Play

Od momentu wprowadzenia zaufanej aktywności w internecie w zeszłym roku zespół Chrome nadal pracuje nad tą usługą, ułatwiając korzystanie z Bubblewrap, dodając nowe funkcje, takie jak planowana integracja z płatnościami w Google Play, i umożliwiając jej działanie na większej liczbie platform, np. ChromeOS. Ten artykuł zawiera podsumowanie najnowszych i nadchodzących aktualizacji Zaufanej aktywności w internecie.

Nowe funkcje zaokrąglonej folii i zaufanej aktywności w internecie

Bubblewrap ułatwia tworzenie aplikacji, które uruchamiają PWA w zaufanej aktywności w internecie, bez konieczności znajomości narzędzi powiązanych z daną platformą.

Uproszczona konfiguracja

Wcześniej użycie Bubblewrap wymagało ręcznej konfiguracji pakietu Java Development Kit i pakietu Android SDK. Oba te rozwiązania są podatne na błędy. Narzędzie oferuje teraz automatyczne pobieranie zależności zewnętrznych przy pierwszym uruchomieniu.

Jeśli wolisz, nadal możesz użyć istniejącej instalacji zależności, a nowe polecenie doctor ułatwia znajdowanie problemów i zaleca poprawki w konfiguracji, którą można teraz zaktualizować z poziomu wiersza poleceń za pomocą polecenia updateConfig.

Ulepszony kreator

Gdy tworzysz projekt z użyciem init, Bubblewrap potrzebuje informacji, aby wygenerować aplikację na Androida. Narzędzie wyodrębnia wartości z pliku manifestu aplikacji internetowej i w miarę możliwości podaje wartości domyślne.

Możesz zmienić te wartości podczas tworzenia nowego projektu, ale wcześniej znaczenie poszczególnych pól nie było jasne. Okna inicjowania zostały utworzone od nowa, lecz lepiej opisane i weryfikowane dla każdego pola wejściowego.

wyświetlacz: obsługa pełnego ekranu i orientacji

W niektórych przypadkach aplikacja powinna wykorzystywać jak najwięcej ekranu. Podczas tworzenia aplikacji PWA należy w tym celu ustawić pole display w pliku manifestu aplikacji internetowej na fullscreen.

Gdy Bubblewrap wykryje opcję pełnego ekranu w pliku manifestu aplikacji internetowej, skonfiguruje aplikację na Androida tak, aby uruchamiała się też w trybie pełnoekranowym lub w trybie pojemnym zgodnie z zasadami dotyczącymi Androida.

Pole orientation w pliku manifestu aplikacji internetowej określa, czy aplikację należy uruchamiać w orientacji pionowej, poziomej czy w orientacji, której używa obecnie urządzenie. Teraz Bubblewall odczytuje pole pliku manifestu aplikacji internetowej i używa go jako wartości domyślnej podczas tworzenia aplikacji na Androida.

Obie konfiguracje można dostosować w ramach procesu bubblewrap init.

Dane wyjściowe pakietów aplikacji

Pakiety aplikacji to format publikowania aplikacji, który przekazuje ostateczne wygenerowanie pliku APK i podpisanie go w Google Play. W praktyce umożliwia to wyświetlanie użytkownikom mniejszych plików podczas pobierania aplikacji ze sklepu.

Teraz funkcja Bubblewrap pakuje aplikację jako pakiet aplikacji – plik o nazwie app-release-bundle.aab. Zalecamy korzystanie z tego formatu podczas publikowania aplikacji w Sklepie Play, ponieważ będzie on wymagany w drugiej połowie 2021 roku.

Przekazywanie dostępu do geolokalizacji

Użytkownicy oczekują, że aplikacje zainstalowane na ich urządzeniach będą działać konsekwentnie niezależnie od technologii. Gdy użyjesz go w zaufanej aktywności internetowej, uprawnienie GeoLocation można teraz przekazać systemowi operacyjnemu. Po włączeniu użytkownicy będą widzieć te same okna co aplikacje utworzone za pomocą Kotlin lub Javy oraz w tym samym miejscu mogą znaleźć elementy sterujące do zarządzania uprawnieniami.

Tę funkcję można dodać za pomocą dymka, a ponieważ dodaje ona dodatkowe zależności do projektu na Androida, należy ją włączać tylko wtedy, gdy aplikacja internetowa korzysta z uprawnień do geolokalizacji.

Zoptymalizowane pliki binarne

Urządzenia z ograniczoną ilością miejsca na dane są powszechne w niektórych regionach świata, a ich właściciele często preferują mniejsze aplikacje. Aplikacje korzystające z zaufanej aktywności internetowej generują niewielkie pliki binarne, co eliminuje część niepokojów użytkowników.

Ta funkcja została zoptymalizowana przez zmniejszenie listy potrzebnych bibliotek Androida, dzięki czemu pliki binarne są mniejsze o 800 KB. W praktyce jest to mniej niż połowa średniego rozmiaru generowanego przez poprzednie wersje. Aby skorzystać z mniejszych plików binarnych, wystarczy zaktualizować aplikację do najnowszej wersji Bubblewrap.

Jak zaktualizować istniejącą aplikację

Aplikacja wygenerowana przez Bubblewrap składa się z aplikacji internetowej i lekkiego kodu na Androida, który otwiera aplikację PWA. Mimo że PWA otwierana w zaufanej aktywności internetowej podlega tym samym cyklom aktualizacji co każda aplikacja internetowa, natywny kod może i powinien być aktualizowany.

Musisz zaktualizować aplikację, aby używała najnowszej wersji opakowania z najnowszymi poprawkami błędów i funkcjami. Gdy jest zainstalowana najnowsza wersja Bubblewrap, polecenie update zastosuje najnowszą wersję otoki w istniejącym projekcie:

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

Innym powodem, dla którego warto zaktualizować te aplikacje, jest zastosowanie do nich zmian w pliku manifestu internetowego. Do tego celu użyj nowego polecenia merge:

bubblewrap merge
bubblewrap update
bubblewrap build

Zmiany w kryteriach jakościowych

W Chrome 86 wprowadzono zmiany w kryteriach jakości zaufanej aktywności w internecie. Zostały one w pełni wyjaśnione w artykule Zmiany kryteriów jakości aplikacji PWA korzystających z zaufanej aktywności w internecie.

W skrócie musisz zadbać o to, aby aplikacje obsługiwały te scenariusze, aby zapobiec ich awarii:

  • Brak weryfikacji linków do zasobów cyfrowych podczas uruchamiania aplikacji
  • Nie udało się zwrócić kodu HTTP 200 w przypadku żądania zasobu sieciowego offline
  • Zwrócenie błędu HTTP 404 lub 5xx w aplikacji.

Oprócz zapewnienia, że aplikacja przejdzie weryfikację Digital Asset Links, skrypt service worker może też wykonać pozostałe scenariusze:

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 stosuje sprawdzone metody i usuwa gotowe elementy, gdy są używane mechanizmy Service Worker. Możesz też użyć wtyczki Workbox do obsługi tych scenariuszy:

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

Płatności w Google Play

Oprócz umożliwienia aplikacji sprzedaży produktów cyfrowych i subskrypcji w Sklepie Play Płatności w Google Play zapewniają narzędzia do zarządzania katalogiem, cenami i subskrypcjami, przydatne raporty oraz proces płatności obsługiwany przez Sklep Play. Jest on także wymagany w przypadku aplikacji sprzedających produkty cyfrowe, publikowane w Sklepie Play.

Chrome 88 zostanie wprowadzony na Androida w ramach wersji próbnej origin, która umożliwia integrację Trusted Web Activities, Payment Request API i Digital Goods API w celu implementacji procesów zakupów za pomocą Płatności w Google Play. Spodziewamy się, że wersja próbna origin będzie również dostępna w ChromeOS w wersji 89.

Ważne: interfejs Google Play Billing API ma własną terminologię oraz komponenty klienta i backendu. Ta sekcja obejmuje tylko niewielką część interfejsu API, który dotyczy korzystania z interfejsu Digital Goods API i Trusted Web Activity. Przed integracją z aplikacją produkcyjną przeczytaj dokumentację dotyczącą płatności w Google Play i zapoznaj się z jej pojęciami.

Podstawowy przepływ

Menu Konsoli Play

Aby dostarczać produkty cyfrowe w Sklepie Play, musisz skonfigurować swój katalog w Sklepie Play, a także połączyć Sklep Play jako formę płatności w aplikacji PWA.

Aby skonfigurować katalog, najpierw znajdź sekcję Produkty w menu po lewej stronie Konsoli Play:

Znajdziesz tu opcję wyświetlania dotychczasowych subskrypcji i produktów w aplikacji, a także przycisk „Utwórz”, aby dodać nowe.

Produkty w aplikacji

Szczegóły usługi

Aby utworzyć nowy produkt w aplikacji, będziesz potrzebować jego identyfikatora, nazwy, opisu i ceny. Ważne jest, aby tworzyć znaczące i łatwe do zapamiętania identyfikatory produktów. Będą one potrzebne później, a po utworzeniu nie będzie można ich już zmienić.

Podczas tworzenia subskrypcji musisz też określić okres rozliczeniowy. Możesz podać informacje o korzyściach z subskrypcji i dodać takie funkcje jak bezpłatny okres próbny, cenę dla nowych użytkowników, okres prolongaty czy opcję odnowienia.

Po utworzeniu każdego produktu możesz go udostępnić w aplikacji, aktywując go.

Jeśli wolisz, możesz dodawać swoje produkty za pomocą interfejsu Play Developers API.

Po skonfigurowaniu katalogu następnym krokiem jest skonfigurowanie procesu płatności z PWA. Aby to zrobić, użyj kombinacji interfejsów Digital Goods API i Payment Request API.

Pobieranie ceny produktu za pomocą interfejsu Digital Goods API

Gdy korzystasz z Płatności w Google Play, zadbaj o to, by cena wyświetlana użytkownikom odpowiadała cenie na stronie z informacjami o aplikacji. Ręczne synchronizowanie tych cen byłoby niemożliwe, dlatego interfejs Digital Goods API umożliwia aplikacji internetowej wysyłanie zapytań o ceny do odpowiedniego dostawcy usług płatniczych:

// 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;
}

Możesz wykryć obsługę interfejsu Digital Goods API, sprawdzając, czy w obiekcie window jest dostępny getDigitalGoodsService().

Następnie wywołaj window.getDigitalGoodsService(), podając jako parametr identyfikator płatności w Google Play. Spowoduje to zwrócenie instancji usługi Płatności w Google Play, a inni dostawcy mogą wdrożyć obsługę interfejsu Digital Goods API i będą mieć różne identyfikatory.

Na koniec wywołaj getDetails() w odniesieniu do obiektu Płatności w Google Play, przekazując kod SKU produktu jako parametr. Zwraca ona obiekt details zawierający zarówno cenę, jak i walutę elementu, który można wyświetlić użytkownikowi.

Rozpocznij proces zakupu

Interfejs Payment Request API umożliwia dokonywanie zakupów w internecie i jest używany do integracji z Płatnościami w Google Play. Jeśli dopiero zaczynasz korzystać z Payment Request API, zapoznaj się z tym artykułem Jak działa Payment Request API.

Aby korzystać z interfejsu API z Płatnościami w Google Play, musisz dodać instrument płatniczy wykorzystujący obsługiwaną metodę https://play.google.com/billing oraz kod SKU jako część danych tego instrumentu:

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

Następnie w zwykły sposób utwórz obiekt PaymentRequest i używaj interfejsu API w zwykły sposób.

const request = new PaymentRequest(supportedInstruments, details);

Potwierdź zakup

Po zakończeniu transakcji musisz potwierdzić płatność za pomocą interfejsu Digital Goods API. Obiekt odpowiedzi z PaymentRequest będzie zawierać token, którego używasz do potwierdzenia transakcji:

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');

Interfejs Digital Goods API i Payment Request API nie mają wiedzy o tożsamości użytkownika. Dlatego musisz powiązać zakup z użytkownikiem w Twoim backendzie i upewnić się, że ma on dostęp do zakupionych produktów. Tworząc powiązanie zakupu z użytkownikiem, pamiętaj, aby zapisać token zakupu, ponieważ może on być potrzebny do weryfikacji, czy zakup został anulowany lub jego zamówienie zostało anulowane, a także czy subskrypcja jest nadal aktywna. Zapoznaj się z interfejsami Real Time Developer Notification API oraz Google Play Developer API, ponieważ zapewniają one punkty końcowe do obsługi takich przypadków w backendzie.

Sprawdzanie istniejących upoważnień

Użytkownik mógł wykorzystać kod promocyjny lub mieć subskrypcję Twojego produktu. Aby sprawdzić, czy użytkownik ma odpowiednie uprawnienia, możesz wywołać polecenie listPurchases() w usłudze produktów cyfrowych. Zwrócone zostaną wszystkie zakupy, których klient dokonał w Twojej aplikacji. W tym miejscu możesz też potwierdzić wszelkie niepotwierdzone zakupy, by mieć pewność, że użytkownik prawidłowo korzysta ze swoich uprawnień.

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

Prześlij do Sklepu Play na urządzeniu z ChromeOS

Zaufane aktywności w internecie są też dostępne w Sklepie Play w ChromeOS od wersji 85. Proces umieszczania aplikacji w sklepie jest taki sam w ChromeOS i w przypadku Androida.

Gdy utworzysz pakiet aplikacji, Konsola Play przeprowadzi Cię przez wszystkie wymagane czynności. W dokumentacji Konsoli Play znajdziesz pomoc dotyczącą tworzenia informacji o aplikacji, zarządzania plikami APK i innymi ustawieniami, a także instrukcje testowania i bezpiecznego publikowania aplikacji.

Aby ograniczyć działanie aplikacji tylko do Chromebooków, podczas inicjowania aplikacji w dymku dodaj flagę --chromeosonly:

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

Tworząc aplikację ręcznie, bez Bubblewrap, dodaj flagę uses-feature do pliku manifestu Androida:

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

Jeśli udostępniasz informacje o aplikacji na Androida, jedyna wersja pakietu w ChromeOS zawsze musi być wyższa niż wersja pakietu aplikacji na Androida. Możesz ustawić wersję pakietu ChromeOS o wiele wyższy numer niż wersja na Androida, aby nie trzeba było aktualizować obu wersji każdej wersji.