Gepubliceerd: 2 december 2020
Sinds de introductie van Trusted Web Activity heeft het Chrome-team de functionaliteit voor Bubblewrap verbeterd. We hebben extra functies toegevoegd, zoals integratie met Google Play Billing , en ervoor gezorgd dat de app op meer platforms werkt, zoals ChromeOS .
Bubblewrap en Trusted Web Activity-functies
Met Bubblewrap kunt u apps maken die uw PWA's starten in een Trusted Web Activity, zonder dat u kennis nodig hebt van platformspecifieke tools.
Vereenvoudigde installatiestroom
Voorheen vereiste Bubblewrap het handmatig instellen van de Java Development Kit en de Android SDK, die beide foutgevoelig zijn. De tool biedt nu de mogelijkheid om de externe afhankelijkheden automatisch te downloaden wanneer deze voor de eerste keer wordt uitgevoerd.
U kunt er nog steeds voor kiezen om een bestaande installatie van de afhankelijkheden te gebruiken als u dat liever wilt. De nieuwe opdracht doctor
helpt bij het vinden van problemen en geeft aanbevelingen voor oplossingen voor de configuratie. Deze kan nu worden bijgewerkt vanaf de opdrachtregel met de opdracht updateConfig
.
Verbeterde wizard
Bij het aanmaken van een project met init
heeft Bubblewrap informatie nodig om de Android-app te genereren. De tool extraheert waarden uit het webapp-manifest en biedt waar mogelijk standaardwaarden.
U kunt deze waarden wijzigen bij het aanmaken van een nieuw project, maar voorheen was de betekenis van elk veld niet duidelijk. De initialisatiedialogen zijn opnieuw opgebouwd met betere beschrijvingen en validatie voor elk invoerveld.
Ondersteuning voor volledig scherm en oriëntatie
In sommige gevallen wilt u dat uw toepassing zoveel mogelijk van het scherm gebruikt. Bij het bouwen van PWA's implementeert u dit door het display
van het web-appmanifest in te stellen op fullscreen
.
Wanneer Bubblewrap de optie voor volledig scherm in het web-app-manifest detecteert, wordt de Android-applicatie zo geconfigureerd dat deze ook in volledig scherm of immersieve modus wordt gestart, in Android-specifieke termen.
Het veld orientation
van het Web App Manifest definieert of de applicatie moet worden gestart in de staande modus, liggende modus of in de stand waarin het apparaat zich momenteel bevindt. Bubblewrap leest nu het veld Web App Manifest en gebruikt dit als standaard bij het maken van de Android-app.
U kunt beide configuraties aanpassen als onderdeel van de bubblewrap init
-flow.
AppBundles-uitvoer
App Bundles is een publicatieformaat voor apps dat de uiteindelijke APK-generatie en -ondertekening delegeert aan Play. In de praktijk maakt dit het mogelijk om kleinere bestanden aan gebruikers te leveren wanneer ze de app downloaden uit de Store.
Bubblewrap verpakt de applicatie nu als een appbundel, in een bestand met de naam app-release-bundle.aab
. Je kunt dit formaat het beste gebruiken bij het publiceren van apps in de Play Store, aangezien dit vanaf 2021 vereist is.
Geolocatiedelegatie
Gebruikers verwachten dat applicaties die op hun apparaten zijn geïnstalleerd, consistent werken, ongeacht de technologie. Bij gebruik binnen een vertrouwde webactiviteit kan de GeoLocation- machtiging nu worden gedelegeerd aan het besturingssysteem. Wanneer deze machtiging is ingeschakeld, zien gebruikers dezelfde dialoogvensters als apps die met Kotlin of Java zijn gebouwd, en vinden ze op dezelfde plek de opties om de machtiging te beheren.
De functie kan worden toegevoegd via Bubblewrap en omdat het extra afhankelijkheden toevoegt aan het Android-project, moet u deze alleen inschakelen wanneer de webapp de Geolocatie-machtiging gebruikt.
Geoptimaliseerde binaire bestanden
Apparaten met beperkte opslagruimte zijn in bepaalde delen van de wereld gebruikelijk, en eigenaren van die apparaten geven vaak de voorkeur aan kleinere applicaties. Applicaties die gebruikmaken van Trusted Web Activity produceren kleine binaire bestanden, wat een deel van de zorgen bij deze gebruikers wegneemt.
Bubblewrap is geoptimaliseerd door de lijst met benodigde Android-bibliotheken te verkleinen, wat resulteert in gegenereerde binaries die 800k kleiner zijn. In de praktijk is dat minder dan de helft van de gemiddelde grootte van eerdere versies. Om te profiteren van de kleinere binaries, hoeft u uw app alleen maar bij te werken met de nieuwste versie van Bubblewrap.
Een bestaande app updaten
Een door Bubblewrap gegenereerde applicatie bestaat uit een webapplicatie en een lichtgewicht Android-wrapper die de PWA opent. Hoewel de PWA die in een vertrouwde webactiviteit wordt geopend dezelfde updatecycli volgt als elke andere webapp, kan en moet de native wrapper worden bijgewerkt.
Je moet je app bijwerken om ervoor te zorgen dat deze de nieuwste versie van de wrapper gebruikt, met de nieuwste bugfixes en functies. Met de nieuwste versie van Bubblewrap geïnstalleerd, past de update
opdracht de nieuwste versie van de wrapper toe op een bestaand project:
npm update -g @bubblewrap/cli
bubblewrap update
bubblewrap build
Een andere reden om deze applicaties bij te werken, is ervoor te zorgen dat wijzigingen in het webmanifest worden toegepast op de applicatie. Gebruik hiervoor de nieuwe merge
-opdracht:
bubblewrap merge
bubblewrap update
bubblewrap build
Updates van de kwaliteitscriteria
In Chrome 86 zijn wijzigingen doorgevoerd in de kwaliteitscriteria voor Trusted Web Activity. Deze worden volledig uitgelegd in Wijzigingen in kwaliteitscriteria voor PWA's die Trusted Web Activity gebruiken .
Kort samengevat moet u ervoor zorgen dat uw applicaties de volgende scenario's aankunnen om te voorkomen dat ze crashen:
- Het niet verifiëren van koppelingen naar digitale activa bij de lancering van de applicatie
- Het is niet mogelijk om HTTP 200 te retourneren voor een offline netwerkbronaanvraag
- Terugkeer van een HTTP 404- of 5xx-fout in de applicatie.
Naast het garanderen dat de applicatie de Digital Asset Links-validatie doorstaat, kunnen de overige scenario's door een service worker worden afgehandeld:
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 bouwt best practices in en verwijdert boilerplate bij het gebruik van service workers. U kunt ook overwegen een Workbox-plug-in te gebruiken om deze scenario's af te handelen:
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,
});
}
}