Bubblewrap: How To Publish Your Progressive Web App (PWA) In The Google Play Store

Traditionally, when developers wanted to distribute their web-based apps through app stores like Google Play, there was only one option: Apache Cordova. In the meantime, Progressive Web Apps (PWA) have arrived. The life of a PWA starts in the browser, and users can choose to install the application to the home screen for faster access. Still, there are lots of reasons why developers might want to distribute their applications via app stores. With the help of Trusted Web Activities (TWA) and Bubblewrap, developers can distribute their existing PWA through the Play Store for Android and Chrome OS, combining the power of both worlds.

In diesem Artikel:

Christian Liebel ist Consultant bei Thinktecture. Sein Fokus liegt auf Webstandards und Progressive Web Apps. Er vertritt Thinktecture beim W3C.

What Are Progressive Web Apps, Anyway?

Progressive Web Apps (PWA) are web-based applications that fulfill specific criteria, such as being responsive, app-like, and offline-capable. Leveraging a single code base, PWAs run on any modern browser (Chrome, Edge, Firefox, Safari), any desktop operating system (Linux, macOS, Windows, Chrome OS), and any mobile OS (Android, iOS, iPadOS). Developers can deploy PWAs by merely uploading their source files (HTML, CSS, JavaScript, and assets) to a server—no approval process, no app store guidelines. The PWA can be updated by uploading new files to the server.

Progressive Web Apps are deployed like any other website—a Service Worker makes them available offline.

Users open a Progressive Web App by entering its URL in the browser. The browser then downloads the source files of the application. PWAs use a Service Worker, a central proxy, to store a copy of the source files in a local cache. When offline, the Service Worker delivers the source files from the cache, and the application continues to work. Typically, PWAs follow the Single-Page Application (SPA) pattern. This kind of application downloads all source files once and then works in-memory, i.e. view changes do not lead to roundtrips to the server. This approach makes this type of application very performant and mimics the way native apps work.

If users want faster access to the Progressive Web App, they can add it to the home screen or program list of their platform. This is when the Web App Manifest comes in. A manifest is a JSON-based file, typically named manifest.webmanifest, or manifest.json. The manifest defines the appearance of the installed Progressive Web App, its name, icon, display mode, and so on.

There are many reasons why developers would want to publish their applications in app stores:

  • they have existing apps in the store with a large user base
  • they expect their users to search the store to install applications
  • their competitors have a store app as well

Trusted Web Activities to the Rescue

Thanks to Trusted Web Activities (TWA), developers can reuse the same PWA deployment and create a Play Store package without writing a single line of native code. In the case of TWAs, developers upload an almost empty APK to the app store. The APK only contains a link to the website that should be shown.

Backed by a library called android-browser-helper, a TWA opens a compatible browser (Chrome 72+, Edge 45.05+, Brave, Vivaldi, Fenix/Firefox Nightly). It creates a Custom Tab in which the PWA is hosted. This way, the TWA shares its state (cookies, storage) with the browser. If no compatible browser is installed, the application will not launch, but start to the default browser with the PWA’s URL instead.

Trusted Web Activities link to an existing PWA. Digital Asset Links make sure it is authorized to do so.

The term trusted in TWA indicates that a trust relationship is required between the TWA and the website delivering the source files. Websites have to authorize the resulting APK bundle by providing its public signing key. That means developers need to upload the Digital Asset Links (a file called assetlinks.json) to the .well-known folder of the origin they want to deliver their source files from (e.g., https://example.com/.well-known/assetlinks.json). If the APK is not signed with the matching private key, the TWA will not launch, but the default browser will open with the given URL instead.

In the last step, the developer uploads the APK bundle into the Google Play Store where it has to meet the store’s guidelines and be approved, same as any native app. When opened for the first time, TWAs show a banner (e.g., Running in Chrome) at the bottom of the screen. Apart from that, there’s no visible difference between native applications and a TWA.

Please note that PWAs, even when shipped as a TWA, can only call web platform APIs. Fortunately, many APIs with native power have landed on the web over the past years (such as push notifications, hardware-accelerated 2D/3D visualizations, gamepad/pen/touch input, or clipboard access). Thanks to efforts like Project Fugu, the Web App Gap will continue to close in the future. However, in contrast to applications packaged with Apache Cordova (or its contender Ionic Capacitor), TWAs cannot call arbitrary native APIs.

Frictionless TWA Generation with Bubblewrap

Bubblewrap is an open-source command-line tool that simplifies TWA generation. It requires Node.js 10 or above, the Java Development Kit (JDK) 8, and the Android SDK installed on the system. Developers can install the CLI by calling npm i -g @bubblewrap/cli on the command line. To create a new Bubblewrap project in the current directory, developers call bubblewrap init --manifest https://example.com/manifest.webmanifest, where --manifest points to the Web App Manifest of the PWA. Bubblewrap then downloads the manifest and launches an interactive assistant. When running for the first time, the CLI asks for the locations of the JDK and Android SDK. More information about the SDK locations on the different platforms can be found in the Bubblewrap CLI documentation.

Bubblewrap's interactive assistant guides the developer through the TWA generation process

The interactive assistant asks for different properties the resulting Android application should have, such as the application name, icons, or colors. Where applicable, the assistant suggests using the values that were defined in the PWA’s Web App Manifest. Also, the developer either needs to provide an Android Keystore (in case they already have an existing Play Store app), or create a new one. The result is a native Android app project that can also be opened in Android Studio. The project configuration is stored in the file twa-manifest.json.

To compile an APK from the project, developers run the bubblewrap build command. As part of this process, Bubblewrap also validates the Progressive Web App by running it against the audit tool Lighthouse, which checks the correct usage of PWA features and other best practices. Also, Bubblewrap creates the assetlinks.json file that must be uploaded to the PWA’s origin, as noted above.

As the Progressive Web App updates automatically and separately, the Trusted Web Activity theoretically would not have to be touched again. In case developers need to update their TWA for some reason, they can run the bubblewrap update command, which automatically increments the APK’s version code.

Case Study: Top-Notch Web Apps for Android 6

We recently migrated our first customer to TWA and traditionally we would have used a Cordova app. The customer wanted to replace their existing native Android application in the Play Store by their new web application. Apart from modern Android devices, the customer needs to support devices down to Android 6.0 Marshmallow. The integrated WebView of Android 6.0, which Cordova would use by default, doesn’t support all the CSS features the client’s web application requires. Crosswalk, which bundles a Chromium browser into the application package, would significantly increase the bundle size and is no longer maintained, posing a security risk to users.

Fortunately, recent versions of Chrome can be installed on this Android version, and the customer already had a working PWA. So, we generated a Trusted Web Activity from the PWA with the help of Bubblewrap. Since the CLI allows modification of the app version and offers to provide an existing Keystore, it makes it very easy to replace existing native applications in the store. There’s no visible difference between a native application and the TWA. As a result, Trusted Web Activities are also a great tool to provide modern web apps via the Play Store for legacy devices.


Our recommendation for developers is to aim for a Progressive Web App whenever possible. Using the very same codebase and easy way of deployment, developers cannot only address browsers, desktop, and mobile systems, but also app stores like Google Play, the Microsoft Store, or the Samsung Galaxy Store (currently US-only). For the Apple App Store, developers need to ship their application as a part of the application bundle, which requires wrappers like Apache Cordova or Capacitor.

In case you want your PWA to be present in the Google Play Store, Trusted Web Activities and Bubblewrap are the way to go. The process is frictionless, both for Play Store newcomers and for developers who want to replace their existing native application with a PWA. Again, the cross-platform story holds up: One codebase, maximum reach.

Thanks to André Bandarra and Ursula Brummack for reviewing this post.


Aktuelle Artikel, Screencasts, Webinare und Interviews unserer Experten für Sie

Verpassen Sie keine Inhalte zu Angular, .NET Core, Blazor, Azure und Kubernetes und melden Sie sich zu unserem kostenlosen monatlichen Dev-Newsletter an.

Newsletter Anmeldung
Diese Artikel könnten Sie interessieren
Low-angle photography of metal structure

AI-Funktionen zu Angular-Apps hinzufügen: lokal und offlinefähig

Künstliche Intelligenz (KI) ist spätestens seit der Veröffentlichung von ChatGPT in aller Munde. Wit WebLLM können Sie einen KI-Chatbot in Ihre eigenen Angular-Anwendungen integrieren. Wie das funktioniert und welche Vor- und Nachteile WebLLM hat, lesen Sie hier.

Adding Superpowers to your Blazor WebAssembly App with Project Fugu APIs

Blazor WebAssembly is a powerful framework for building web applications that run on the client-side. With Project Fugu APIs, you can extend the capabilities of these apps to access new device features and provide an enhanced user experience. In this article, learn about the benefits of using Project Fugu APIs, the wrapper packages that are available for Blazor WebAssembly, and how to use them in your application.

Whether you're a seasoned Blazor developer or just getting started, this article will help you add superpowers to your Blazor WebAssembly app.
Project Fugu

Dark Mode Support – Real-World PWA: The Making Of Paint.Js.Org – Part 5

In part five of the series about the making of the web-based Microsoft Paint clone paint.js.org, I want to show how to implement support for dark mode in your web applications.
Project Fugu

Accessing Files & File Handler – Real-World PWA: The Making Of Paint.Js.Org – Part 4

In this fourth part of the series about the Microsoft Paint remake on paint.js.org, I want to demonstrate how you can save your drawings to your local disk, read them back later and how to add your web app as a handler for certain file extensions.
Project Fugu

Copy & Paste Images – Real-World PWA: The Making Of Paint.Js.Org – Part 3

In part three of the series about the making of the web-based Microsoft Paint clone paint.js.org, I want to show how you can copy drawings from the Paint clone to other applications and paste them back.
Project Fugu

Canvas & Input – Real-World PWA: The Making Of Paint.Js.Org – Part 2

After introducing into the project about the web-based Microsoft Paint clone in the first part of this series and talking about the choice of Web Components and the architecture of paint.js.org, I now want to demonstrate how I implemented the drawing functionality.