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
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.
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.