Try Vaadin's Visual View Builder for seamless collaboration, prototype sharing, and code generation.

Submitting a PWA to Google Play Store using Bubblewrap

Mikael Sukoinen
Mikael Sukoinen
On Jan 5, 2021 5:42:00 PM

This tutorial shows how you build and submit your progressive web application (PWA) to the Google Play Store. We use the PWA from our Modern Web App tutorial series as an example and wrap it as a Trusted Web Activity (TWA) using the Bubblewrap CLI by Google Chrome Labs. You can find more details about Bubblewrap in their GitHub repository.

Every PWA submitted to Google Play Store must pass their review process before it is published in the store.


Google accounts

There is a one-time $25 sign-up fee for a Google Developer account.


At a minimum, you need the following images to upload your application:

  • High-resolution icon

  • Featured graphic

You can find a full list of requirements, recommendations and guidelines in the Play Console Help documentation.

Tools and software

You need the following software before creating a TWA from your PWA. Install the following tools and make a note of their installation paths for the next step:

Older or newer Java versions may not be compatible with the Bubblewrap CLI.

A Progressive Web Application

We’ll be using the Bubblewrap CLI to wrap a PWA for deployment to the Google Play Store.

If you don’t have a PWA, we recommend getting started with Vaadin. Our comprehensive tutorial series, and technical documentation make it easy to build your first PWA!

Alternatively, follow one of our framework-independent basic tutorials to turn your existing web app into a PWA.

Install the Bubblewrap CLI

After your have installed Node, JDK 8 and Android SDK, run the npm i -g @bubblewrap/cli command in your terminal to download and install the Bubblewrap CLI:

mikael@MacBook-Pro ~ %  i -g @bubblewrap/cli

/usr/local/bin/bubblewrap - /usr/local/lib/node_modules/@bubblewrap/cli/bin/bubblewrap.js
+ @bubblewrap/cli@1.5.0
added  packages from  contributors  .225s
If you already have an older version of Bubblewrap installed, you can update to the latest version using the npm install -g npm command.
mikael@MacBook-Pro ~ % npm install -g npm
/usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
/usr/local/bin/npx -> /usr/local/lib/node_modules/npm/bin/npx-cli.js
+ npm@6.14.8
added 17 packages from 3 contributors, removed 18 packages and updated 20 packages in 4.452s

The installer will ask for the installation path for the Java 8 JDK and Android SDK. Enter the installation directory path you noted in the previous step:

? Path to the JDK: /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk
? Path to the Android SDK: /usr/local/lib/node_modules/@bubblewrap/cli/node_modu
Initializing application from Web Manifest:
	-  /Users/mikael/Downloads/pwa-tutorial-basic-master/manifest.json

Convert your PWA to a TWA

Initialize Bubblewrap by running the bubblewrap init --manifest=https://COMPLETE URL/manifest.json command. Replace COMPLETE_URL with the URL link of your PWA. The example below is running an app on a local HTTP server:

mikael@MacBook-Pro ~ % bubblewrap init --manifesthttp://localhost:5000/manifest.json
,-----.        ,--.  ,--.  ,--.
   /_,--.,--  -.  -.  ,---.,--.   ,--,--.--.,--,--.,---.
  .-.       .-.  .-.    .-.    ,-.   .-. 
   '   -             -------      --  -
Initializing application from Web Manifest:

The Bubblewrap CLI client automatically extracts values from the manifest.json file, but you can configure your application details manually, if you like.

You can skip the optional details by pressing the Enter key.
Web app details /5

The application generated by Bubblewrap will  a Progressive Web App when
started from the Android launcher. Please enter the following details about
the PWA:

	- Domain: the domain / origin where the PWA is hosted.

	- URL path: an URL path relative to the root of the origin,
	  opened when the application is started from the home screen.

		- To /
		- To /path-to-pwa/

? Domain: 
? URL path: http://localhost:5000/manifest.json

Android app details /5

Please, enter details regarding how the Android app will  when installed
into a device:

	- Application name: the name used   places,
	  including the App information  and on the Play Store.

	- Short name: an alternate name  the app, limited to
	   characters, used on a device launch screen.

	- Application ID: also known as Package Name, this is
	  the unique identifier  the application on an Android device or
	  the Play Store. The name must contain at least two segments,
	  separated by dots, each segment must start with a letter and all
	  characters must be alphanumeric or an underscore _.

	- Display mode: how the app will be displayed on the
	  device  when started. The default mode, used by  apps,
	  is standalone. fullscreen causes the device status bar and
	  navigation bars to be removed and is suitable  games or media
	  players. For  information on the status bars and navigation
	  bar on Android, go to:

	- Status bar color: sets the status bar color used when the
	  application is  foreground. Example: 

? Application name: vaadin_pwatest
? Short name: vpwa
? Application ID: localhost_5000.twa
? Display mode: standalone
? Status bar color: 

Launcher icons and splash  /5

The Android app requires an image  the launcher icon. It also displays a
splash   the web content is loading, to avoid displaying a flash of
a blank white page to users.

	- Splash  color: sets the background colour used  the
	  splash screen. Example: 

	- Icon URL: URL to an image that is at least 512x512px. Used to
	  generate the launcher icon  the application and the image 
	  the splash screen.

	- Maskable Icon URL Optional: URL to an image that is at least
	  512x512px to be used when generating maskable icons. Maskable
	  icons should  good when their edges are removed by an icon
	  mask. They will be used to display adaptive launcher icons on the
	  Android home screen.

? Splash  color: 
? Icon URL: http://localhost:5000/img/icons/icon-512x512.png
? Maskable icon URL:

Optional Features /5

	- Include app shortcuts: This question is only prompted  a
	   section is available on the input Web Manifest. When
	  answered “yes”, Bubblewrap uses the information to generate
	  shortcuts on the Android app. Read  about app shortcuts at

	- Monochrome icon URL: URL to an image that is at least 48x48px to
	  be used when generating monochrome icons. Monochrome icons should
	   good when displayed with a single color, the PWA's
	  theme_color. They will be used  notification icons.

? Monochrome icon URL:

Generate or locate signing keys

You need Android signing keys to deploy to the Play Store. The Bubblewrap CLI client will use an existing key at ./android.keystore, if you already have a key. If you do not, Bubblewrap will prompt you to create new keys:

Signing key information /5

Please, enter information about the key store containing the keys that will be used
to sign the application. If a key store does not exist on the provided path,
Bubblewrap will prompt  the creation of a new keystore.

	- Key store location: The location of the key store  the 

	- Key name: The  used on the key.

Read  about Android signing keys at:

? Key store location: ./android.keystore
? Key name: android
Saving Config to: ./twa-manifest.json
Generating Android Project.
  ████████████████████████████████████████ %

Type Y to begin creating signing keys. Fill in the required details and enter separate passwords for the Key Store and the Key. Note the passwords for the next step.

Signing key creation

An existing key store could could not be found at 

? Do you want to create one now? Yes
? First and Last names eg: John Doe: Mikael Sukoinen
? Organizational Unit eg: Engineering Dept: Marketing
? Organization eg: Company Name: Vaadin
? Country  letter code: FI
? Password  the Key Store: ***********************
? Password  the Key: ***************
keytool Signing Key created successfully

Project generated successfully. Build it by running bubblewrap build

Build the APK

Run the bubblewrap build command to build an Android application package (APK) from the project.

mikael@MacBook-Pro ~ % bubblewrap build
,-----.        ,--.  ,--.  ,--.
   /_,--.,--  -.  -.  ,---.,--.   ,--,--.--.,--,--.,---.
  .-.       .-.  .-.    .-.    ,-.   .-. 
   '   -             -------      --  -
Installing Android Build Tools. Please,  and accept the license agreement.
build Installing Build Tools
License android-sdk-license:             % Computing updates.

Terms and Conditions

This is the Android Software Development Kit License Agreement


Accept the license and terms by pressing Y. Then enter your Key Store password:

Please, enter passwords  the keystore ./android.keystore and  android.

? Password  the Key Store: ***********************
? Password  the Key: ***************

Building the Android App.
	- Generated Android APK at ./app-release-signed.apk
	- Generated Digital Asset Links  at ./assetlinks.json

This process outputs 2 files:

  1. assetlinks.json that validates the domain within a TWA.

  2. app-release-sgned.apk, an Android application that can be tested on a development device and submitted to the Play Store.

The build command also tests the application with Google’s Lighthouse to validate the build and check for best PWA practises.

Finally, add the assetlinks.json file to your web application’s root directory at .well-known/assetlinks.json.

Run the bubblewrap install command with a development device or Android emulator connected to test your app locally. You can find detailed instructions in the Android Developer documentation.

Submit to Play Store

You can now sign in to the Google Play Console to submit your packaged PWA. You can find detailed instructions on how to upload and review your application in the Play Console Help documentation.

Android developer dashboard

Source code on GitHub.

Next steps

Congratulations on submitting your application! If you are looking for more information on PWAs, check out our PWA Handbook. If you are new to progressive web app development, I’d recommend our comprehensive tutorial series that takes you through every step from start to deployment of a complete PWA with Vaadin.

Mikael Sukoinen
Mikael Sukoinen
Mikael has a passion for writing text, code and music. He’s currently utilising his skills to explain difficult concepts in plain language at Vaadin Ltd.
Other posts by Mikael Sukoinen