Co nowego w aplikacjach internetowych w Google Play

Opublikowano: 2 grudnia 2020 r.

Od czasu wprowadzenia zaufanej aktywności internetowej zespół Chrome ułatwił korzystanie z niej za pomocą Bubblewrap. Dodaliśmy nowe funkcje, takie jak integracja z Płatnościami w Google Play, i umożliwiliśmy działanie na większej liczbie platform, np. ChromeOS.

Funkcje Bubblewrap i zaufanej aktywności internetowej

Bubblewrap pomaga tworzyć aplikacje, które uruchamiają PWA w ramach zaufanej aktywności internetowej, bez konieczności znajomości narzędzi specyficznych dla danej platformy.

Uproszczony proces konfiguracji

Wcześniej korzystanie z Bubblewrap wymagało ręcznego skonfigurowania pakietu Java Development Kit i Android SDK, co było podatne na błędy. Narzędzie oferuje teraz automatyczne pobieranie zależności zewnętrznych przy pierwszym uruchomieniu.

Jeśli wolisz, możesz nadal używać dotychczasowej instalacji zależności. Nowe polecenie doctor pomaga znaleźć problemy i zaleca poprawki konfiguracji, którą można teraz zaktualizować z poziomu wiersza poleceń za pomocą polecenia updateConfig.

Ulepszony kreator

Podczas tworzenia projektu za pomocą init Bubblewrap potrzebuje informacji do wygenerowania aplikacji 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 każdego pola nie było jasne. Okna inicjowania zostały przebudowane i zawierają teraz lepsze opisy oraz walidację każdego pola do wprowadzania danych.

Obsługa pełnego ekranu i orientacji wyświetlacza

W niektórych przypadkach możesz chcieć, aby aplikacja wykorzystywała jak największą część ekranu. Podczas tworzenia aplikacji PWA można to zrobić, ustawiając pole display w pliku manifestu aplikacji internetowej na fullscreen.

Gdy Bubblewrap wykryje opcję pełnego ekranu w pliku manifestu aplikacji internetowej, konfiguruje aplikację na Androida tak, aby uruchamiała się również na pełnym ekranie lub w trybie pojemnym (w terminologii Androida).

Pole orientation w pliku manifestu aplikacji internetowej określa, czy aplikacja powinna być uruchamiana w trybie portretowym, trybie poziomym czy w orientacji, której urządzenie aktualnie używa. Bubblewrap odczytuje teraz pole pliku manifestu aplikacji internetowej i używa go jako domyślnego podczas tworzenia aplikacji na Androida.

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

Dane wyjściowe pakietów aplikacji

Pakiety aplikacji to format publikowania aplikacji, który przekazuje Google Play ostateczne generowanie i podpisywanie plików APK. W praktyce umożliwia to udostępnianie użytkownikom mniejszych plików podczas pobierania aplikacji ze sklepu.

Bubblewrap pakuje teraz aplikację jako pakiet aplikacji w pliku o nazwie app-release-bundle.aab. Zalecamy używanie tego formatu podczas publikowania aplikacji w Sklepie Play, ponieważ od 2021 roku jest on wymagany przez ten sklep.

Przekazywanie geolokalizacji

Użytkownicy oczekują, że aplikacje zainstalowane na ich urządzeniach będą działać spójnie, niezależnie od technologii. W przypadku używania w ramach zaufanej aktywności internetowej uprawnienie GeoLocation można teraz przekazać systemowi operacyjnemu. Po włączeniu tej opcji użytkownicy widzą te same okna co w aplikacjach utworzonych w Kotlin lub Java i mogą zarządzać uprawnieniami w tym samym miejscu.

Funkcję można dodać za pomocą Bubblewrap. Ponieważ dodaje ona dodatkowe zależności do projektu aplikacji na Androida, należy ją włączyć tylko wtedy, gdy aplikacja internetowa korzysta z uprawnień do geolokalizacji.

Zoptymalizowane pliki binarne

Urządzenia z ograniczoną ilością miejsca na dane są popularne w niektórych regionach świata, a ich właściciele często wolą mniejsze aplikacje. Aplikacje korzystające z zaufanej aktywności internetowej generują małe pliki binarne, co eliminuje niektóre obawy użytkowników.

Zoptymalizowaliśmy Bubblewrap, zmniejszając listę potrzebnych bibliotek Androida, dzięki czemu wygenerowane pliki binarne są o 800 kB mniejsze. W praktyce jest to mniej niż połowa średniego rozmiaru generowanego przez poprzednie wersje. Aby skorzystać z mniejszych plików binarnych, wystarczy zaktualizować aplikację za pomocą najnowszej wersji Bubblewrap.

Jak zaktualizować istniejącą aplikację

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

Zaktualizuj aplikację, aby mieć pewność, że używa najnowszej wersji kodu, która zawiera najnowsze poprawki błędów i funkcje. Jeśli masz zainstalowaną najnowszą wersję Bubblewrap, polecenie update stosuje najnowszą wersję kodu do istniejącego projektu:

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

Innym powodem aktualizacji tych aplikacji jest zapewnienie, że zmiany w pliku manifestu internetowego zostaną zastosowane w aplikacji. Użyj do tego nowego polecenia merge:

bubblewrap merge
bubblewrap update
bubblewrap build

Zmiany w kryteriach jakości

W Chrome 86 wprowadziliśmy zmiany w kryteriach jakości zaufanej aktywności internetowej, które zostały szczegółowo opisane w artykule Zmiany w kryteriach jakości aplikacji PWA korzystających z zaufanej aktywności internetowej.

Podsumowując, aby zapobiec awariom, musisz upewnić się, że aplikacje obsługują te scenariusze:

  • Niepowodzenie weryfikacji Digital Asset Links podczas uruchamiania aplikacji
  • Niepowodzenie zwrócenia kodu HTTP 200 w przypadku żądania zasobu sieciowego offline
  • Zwrócenie błędu HTTP 404 lub 5xx w aplikacji.

Oprócz upewnienia się, że aplikacja przechodzi walidację Digital Asset Links, pozostałe scenariusze mogą być obsługiwane przez skrypt service worker:

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 zawiera sprawdzone metody i usuwa powtarzający się kod podczas korzystania z skryptów service worker. Możesz też użyć wtyczki Workbox, aby obsłużyć te scenariusze:

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