This TWA stuff rocks! Finally I got my PWA on Google Play Store 🎉

Sven Budak
7 min readFeb 17, 2019

Thinking back of the the time before TWA (Trusted Web Activity) still frightens me. If you wanted to offer a project as a website and an app you had to develop it in two programming languages. There was no way around it. It had to be HTML, CSS and JavaScript for your website and Java, Kotlin or Flutter for your android app. If you drew the short straw you had to write it a third time in Swift for iOS. But now this is a thing of the past. With Chrome update 72 you now can quickly load your website as a full-screen Chrome instance without any Chrome UI elements.

I became aware of this whole topic because of this great article from Maximiliano Firtman:

In this article I would like to focus on giving everyone who knows as little about Native Java as I do an easy and understandable step by step tutorial so that you too can get your website into the Google Play Store without too much pain in the ass.

A clean base makes many things easier. And that’s why I’m really glad that GoogleChromeLabs offers a kind of base / kickstarter repository:

Not much, basically. Simply download, Android Studio and install it with the default settings. Check out the above linked repository and open it in Android Studio.

Now you need to login into with your Google Account and (if you have not already done so) pay $ 25 for unlocking the Google Play Console. After that create a new app and go to App releases > Internal test track > Create release. Here we have to activate the app signing key for this app:

By activation we get the required SHA-256 certificate fingerprint.

Now navigate to app signing and copy your SHA-256 certificate fingerprint: (without the SHA256: at the beginning)

The fingerprint will be publicly visible.

With the SHA-256 fingerprint we now create a Digital Asset Link. To do this, you log in via FTP or SFTP on your web server and create in root: .well-known/assetlinks.json. (do not forget the dot at the beginning!) This file must be accessible at

The content looks like this:

"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "",
"sha256_cert_fingerprints": [

replace hash_of_app_certificate with your SHA256 fingerprint and for think of something like com.companyName.appName (this must match the application ID you set in the app afterwards!) Here is an example.

Believe it or not, the hardest part is already done. Now just open the repository in Android Studio and check this file: app/build.gradle. You will find an array named manifestPlaceholders. Here you can find the relevant information to build the .apk file. The whole thing is well documented and needs no further explanation I think.

Enter your data here, connect your Android smartphone to your PC via USB, enable USB debugging, and click “Run” in Android Studio. Then select your connected mobile phone. (You probably have to to grant the permissions on your smartphone first)

Finally! I feel boundless power!

Now you might see a URL bar similar to a custom Chrome Tab instance. I assure you this will disappear. For me, this was the case after I downloaded the .apk to the internal test in the PlayStore and then installed it on my smartphone. This may have something to do with the fact that the app was not signed at that time.

Now comes the exciting part. I will not go into too much detail of the Google Play Console. This would go beyond the scope of this tutorial. However, I will explain how you create a Signed .apk and set it as Internal test track.

Open Android Studio and go to Build > Generate Signed Bundle / Apk and select APK for now and click Next. Now you create a new keystore file and fill in ALL fields. I didn’t do that and wondered why I could not upload the .apk later. The error message was not very helpful either … I almost went insane until I found out that this was the issue.

Important! Remember the password and the alias. Believe me, you will regret it one day if you don‘t!

Now choose Build Type: “release” and make sure both checkboxes are checked on Signature Versions. Now click on Finish and you have a signed APK.

Important! Remember that after the first upload of your .apk the applicationId cannot be changed anymore. So choose wisely. (This actually does not matter because no one will see anyway)

To upload them, go to App releases > Internal test track > Edit Release in your Google Play Console. Here you can upload them and at the bottom you have to enter a Release Changelog Note. (You will be forced to change the existing text)

You will receive a message telling you that you cannot publish it because no testers are assigned yet. Forget it! This is also a misleading error message. You cannot publish it because the check icons are not green yet. After uploading the .apk you can do these tasks. Then you will be able to publish your app in the internal test track.

This is one of the reasons why I really love Android Studio. In the beginning, I actually manually edited the icons in Affinity Designer for several hours … until I got the redeeming insight that they can be generated automatically in Android Studio with just a few clicks. To do this, right click on your app folder and select New> Image Asset. Everything else on the subject should be self-explanatory. Of course I recommend working with .svg (Vector) graphics.

You can also change the statusBar Color, but this requires a few more customizations which you can read about in this StackOverflow. Do not get confused because of my my questions there. It’s like I said, the first time I got in touch with Android Studio and Native Java.

For me this change is by far the best change / improvement of the last years on the web. I see this as a first step in a direction that should have been taken much earlier. In the next days and weeks I will try to find out how to do the following things:

  • Pass data / variables from the .apk to the website.
  • Splash Screen / Loading Screen with check if Chrome instance is finished loading. You can see that first the Native App gets initialized and after this the Chrome instance starts. This ugly “switch” has to be hidden in order to make the app look even more native.
  • Detect Android Device language and pass it to website / PWA.

If someone has the knowledge and skill, feel free to contact me to extend the Base-TWA repository together so that others only have to adjust config entries for this stuff. 😉

I learned these things because I wanted to put my PWA: Expense Calculator on the PlayStore. Mission accomplished!

Let me know what you think and have fun with the tutorial.

By the way: If you’re one of those people who would rather watch videos than read tutorials, then you should check out this awesome video tutorial produced by Jeff Delaney on this topic:

At this point, I would like to point out his terrific community project! There are not only new tutorials almost every day, but there you can also find the greatest slack community ever!

If you like my tutorial, buy me a coffee:

Stay awesome!