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