Co nowego w aplikacjach internetowych w Google Play

Data publikacji: 2 grudnia 2020 r.

Od czasu wprowadzenia zaufanej aktywności internetowej zespół Chrome ułatwił korzystanie z Bubblewrap. Dodaliśmy dodatkowe funkcje, takie jak integracja z systemem płatności Google Play, i umożliwiliśmy jej działanie na większej liczbie platform, takich jak ChromeOS.

Funkcje Bubblewrap i zaufanej aktywności w internecie

Bubblewrap pomaga tworzyć aplikacje, które uruchamiają PWA w ramach zaufanej aktywności w internecie, bez konieczności znajomości narzędzi do obsługi poszczególnych platform.

Uproszczony proces konfiguracji

Wcześniej korzystanie z Bubblewrap wymagało ręcznej konfiguracji pakietu Java Development Kit i pakietu SDK Androida, które są podatne na błędy. Narzędzie umożliwia teraz automatyczne pobieranie zewnętrznych zależności podczas pierwszego uruchomienia.

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

Ulepszone kreator

Podczas tworzenia projektu za pomocą funkcji 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.

Wartości te możesz zmienić podczas tworzenia nowego projektu, ale wcześniej znaczenie poszczególnych pól nie było jasne. Okna inicjowania zostały przebudowane, aby zawierały lepsze opisy i sprawdzanie poprawności dla każdego pola danych.

Obsługa trybu pełnoekranowego i orientacji

W niektórych przypadkach możesz chcieć, aby aplikacja zajmowała jak najwięcej miejsca na ekranie. W przypadku tworzenia aplikacji PWA można to zaimplementować, ustawiając 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ę również w trybie pełnoekranowym (w terminologii Androida: trybie pełnoekranowym).

Pole orientation z pliku manifestu aplikacji internetowej określa, czy aplikację należy uruchamiać w trybie pionowym, poziomym czy w orientacji używanej obecnie przez urządzenie. Bubblewrap odczytuje 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 pakietu aplikacji

Pakiety aplikacji to format publikowania aplikacji, który przekazuje ostateczne pliki APK do wygenerowania i podpisze je w Google Play. W praktyce oznacza to, że użytkownicy otrzymują mniejsze pliki podczas pobierania aplikacji ze sklepu.

Bubblewrap pakuje aplikację jako pakiet aplikacji w pliku app-release-bundle.aab. Ten format powinieneś preferować podczas publikowania aplikacji w Sklepie Play, ponieważ jest on wymagany przez sklep od 2021 roku.

Delegowanie geolokalizacji

Użytkownicy oczekują, że aplikacje zainstalowane na ich urządzeniach będą działać w sposób spójny, niezależnie od technologii. Uprawnienie GeoLocation używane w ramach zaufanej aktywności internetowej może teraz zostać przekazane systemowi operacyjnemu. Po włączeniu użytkownicy widzą te same okna co w aplikacjach utworzonych w kotlinach lub Javie. W tym samym miejscu znajdują się też opcje zarządzania uprawnieniami.

Funkcję można dodać za pomocą Bubblewrap. Ponieważ powoduje ona dodatkowe zależności w projekcie na Androida, należy ją włączyć tylko wtedy, gdy aplikacja internetowa używa uprawnienia Lokalizacja geograficzna.

Zoptymalizowane pliki binarne

Urządzenia z ograniczoną ilością pamięci są popularne w niektórych regionach świata, a ich właściciele często preferują mniejsze aplikacje. Aplikacje korzystające z zaufanej aktywności w internecie generują małe pliki binarne, co zmniejsza obawy użytkowników.

Bubblewrap został zoptymalizowany przez zmniejszenie listy potrzebnych bibliotek Androida, co spowodowało, że wygenerowane pliki binarne są mniejsze o 800 kB. W praktyce jest to mniej niż połowa średniego rozmiaru generowanego przez poprzednie wersje. Aby korzystać 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 PWA. Mimo że PWA otwierana w ramach zaufanej aktywności internetowej odbywa się w tych samych cyklach aktualizacji co każda aplikacja internetowa, kod natywny można i należy zaktualizować.

Zaktualizuj aplikację, aby upewnić się, że korzysta z najnowszej wersji opakowania z najnowszymi poprawkami błędów i funkcjami. Po zainstalowaniu najnowszej wersji Bubblewrap polecenie update stosuje najnowszą wersję oprogramowania do pakowania do istniejącego projektu:

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

Innym powodem aktualizacji tych aplikacji jest zapewnienie, że zmiany z pliku manifestu internetowego zostały w nich zastosowane. Aby to zrobić, użyj nowego polecenia merge:

bubblewrap merge
bubblewrap update
bubblewrap build

Zmiany kryteriów jakości

W Chrome 86 wprowadzono zmiany w kryteriach jakości zaufanej aktywności internetowej. Więcej informacji znajdziesz w artykule Zmiany kryteriów jakości aplikacji PWA korzystających z zaufanej aktywności internetowej.

Aby zapobiec awariom aplikacji, musisz się upewnić, że obsługują one te scenariusze:

  • Nie udało się zweryfikować linków do zasobów cyfrowych podczas uruchamiania aplikacji
  • Niezwracanie kodu 200 HTTP w przypadku żądania zasobu sieciowego w trybie offline
  • zwracanie w aplikacji błędu HTTP 404 lub 5xx;

Oprócz zapewnienia, że aplikacja przejdzie weryfikację Digital Asset Links, pozostałe scenariusze mogą być obsługiwane przez service workera:

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 wykorzystuje sprawdzone metody i eliminuje powtarzające się fragmenty kodu podczas korzystania z usług działających w tle. Możesz też użyć wtyczki Workbox, aby obsłużyć takie sytuacje:

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