Google Play Store now open for Progressive Web Apps đ±
About 17 min reading time
Disclaimer: Iâm not affiliated with Google Play, Chrome or any other company mentioned. This is not an official statement; usage of the logo and name is just for illustration.
Chrome 72 for Android shipped the long-awaited Trusted Web Activity feature, which means we can now distribute PWAs in the Google Play Store! I played with the feature for a while, digging into the APIs and here you have a summary of whatâs going on, what to expect and how to use it today.
PWAs can now play in the Store #
Chrome 72 for Android is now shipping from the Play Store to all users and this version included Trusted Web Activity (TWA), that in a nutshell is a way to open Chrome in standalone mode (without any toolbar or Chrome UI) within the scope of our own native Android package.
Let me start saying that the publishing process is not straightforward as it should be (such as âenter your URLâ in the Play Console and itâs done.) Itâs also not a way to use the currently available WebAPK and publish it in the store. Itâs a Java API that communicates through services with Chrome and seem to be in the early stages, so there is a lot of manual work to do yet today.
I see this as the first step and Iâm sure better tooling will appear soon (maybe from the community) using these now available APIs to create a one-click to store mechanism. But with the current API, itâs possible to ship a PWAâs launcher. I will share my experience in this article for everyone interested.
For some reason, the feature doesnât appear as shipped yet in Chrome Platform Status and there is still no updated documentation available more than the one published 15 months ago.
*UPDATE 2/5: The Chromium Blog posted a short post confirming TWAs and with some technical confirmations of this article.
*UPDATE 2/1: Paul Kinlan, Lead of Chrome DevRel @ Google confirmed TWA was shipped and docs are just delayed; the reason for the delayed official notification and docs is that the go/no-go for the feature on Chrome 72 was a last-minute decision.
I've just seen the emoji I used đ. I didn't want that oneđ. Thanks for clarification on go/no-go. So you confirm it was a go, right? Hehe. Many people is contacting me saying that it wasn't shipped and I just found a private api đłđ
â Maximiliano Firtman (@firt) February 1, 2019
Here you can watch a video of Pete Le Page explaining TWAs a year ago.
Why publishing a PWA in the store? #
Is the Web Platform, Max! Why do we want to use the Store?
Well, itâs a long discussion, but Iâve been doing consulting with small and big companies for years, and when talking about PWA investment, the store is a recurrent demand. âMy users will look for my app in the Storeâ, âI already have a native app that I want to stop doing, but I donât want to lose my usersâ, âI need to access a native APIâ, or âI want to monetize my PWA.â
From now, publishing your PWA in the Store -as well as from the browser- will be possible. Of course, itâs an opt-in operation. The Play Store is not emulating the Microsoft Store: your PWA wonât be listed in the store if you donât compile your own APK, and publish it.
Advantages over standard PWA installation #
Despite the new distribution mechanism and people finding your app within the store (and even in Googleâs search under âAppsâ), there are some things we may be able to do with a PWA in the Store, such as:
- Offer a Home Screen Widget
- Offer App Shortcuts (when you long press the appâs icon) and other deep integrations with the OS
- Offer a wear OS companion app or Android Auto extension
- Be re-installed after a hard reset or a backup restore on a new phone
- Have background services accessing native features (communication with the PWA is still limited â more on this later)
- Monetize the App â limited today, more on this later
- Have some native screens mixed with PWA content
- Distribute more than one PWA icon in the Launcher and/or home screen pointing to different URLs (within the same host)
- Better internationalization support
Whatâs new here? #
In Google Play Store there are already some PWAs published such as Google Maps Go, Instagram Lite or Twitter Lite. The first one is using some kind of a private pre-TWA version, and the last two are using a WebView that while not ideal, it was the only way to do something like this before TWAs. These apps are adding a lot of native code for some things such as notifications. We want to publish PWAs as web developers, we donât want to write a lot of Java code.
TWA is a special mode on Chrome Custom Tabs, a solution available to native Android apps from Chrome 45 to open an In-App browser.
Is TWA a Hybrid framework, similar to Cordova? #
No. With Cordova or other hybrid solutions, you are typically shipping your web resources (HTML, JS, CSS, etc.) within your APK package. Also, the engine is different and isolated from the usersâ browser, so no session or cache sharing.
This is how a PWA looks like with Trusted Web Activity (Starbucks actually didnât have one yet). I donât see the theme-color implemented yet
With Trusted Web Activity you donât need to package any resource file from your PWA (only native components, in case you want them); all your resources will be downloaded and updated on the fly from your Service Worker. Your PWA will still be rendered with the installed Chrome version, sharing all storage, cache, and sessions with the browser. Therefore, if your user has a session on your website opened when the user installs the app from the Play Store, she will still be logged in. The user is just installing a shortcut to Chrome using a special mode.
Play Store approval requirements (*UPDATE 2/5) #
The URL you use for the Trusted Web Activity must comply with:
- Passing the PWA Criteria (typically today: HTTPS, a Service Worker with a fetch event handler, and a Web App Manifest with a 512px icon, a background_color, and basic other properties set.)
- Performance Score with a minimum of 80/100, tested with Lighthouse (available in Chrome Dev Tools, or as an NPM CLI.)
- All current Google Play Store rules.
As per the Chromium Blog post, published a few days after this article was first published, âApps which fail to meet TWA quality requirements or Play store policy may be denied entry or delisted.â
Iâm not completely sure yet if these requirements will be checked by the Play Store QA team when publishing the app or not.
Security Model of PWAs in the Google Play Store (*UPDATE 2/4) #
Your PWA will run under the browserâs security model, not under your native app one â unless you add native code as well to your APK. Because the Activity will be managed by Chrome, the user should we aware that even if she has just installed the app, she might have session data, local storages and permissions already set for that host. Thatâs why when the user opens the shortcut icon for the first time she will see a âRunning in Chromeâ mini infobar, as stated by Robin Bakker:
Thanks! I guess it all works as it should be, but I meant the bottom bar/banner at first start of the app. On a phone with an older Chrome I noticed the top bar indeed. pic.twitter.com/v1TYuMcMfR
â Robin Bakker (@robinbakker) February 3, 2019
Also, when the user uninstalls the app from the Applicationâs Manager, we will get a warning stating that appâs state and data is still available while in Chrome, so she should clear cache as well if needed. That includes, for example, the Web Push permission, so even if the user uninstalls the app, the app can still send push notification messages. The message was spotted by Henry Lim:
This is interesting for me: this popup will appear after you uninstalled the PWA (which is using TWA btw). cc/ @firt pic.twitter.com/sEU6X5SH4C
â Henry Lim (@henrylim96) February 3, 2019
These dialogs and the reason for them were confirmed by Paul Kinlan, from the Chrome team.
Session storage comes from your browser session, we have to indicate this to users of android apps who don't expect this type of experience.
â Paul Kinlan (@Paul_Kinlan) February 3, 2019
Development options #
For creating an Android Package using TWA we will first need Android Studio. Right now, the options available are kind of experimental and documented only with some open source examples in the Chrome GitHub repository.
We can develop apps with TWA:
- Using a high-level Java Support Library provided by the Chrome team: in this case, you donât need to write any Java or Kotlin native code; you create an Android Studio project (or clone the example), set up some metadata in AndroidManifest.xml from your Web App Manifest and you are done.
The framework will provide the connection with TWA and optional abilities to create a Settings entry in the Android device and to make Web Push notifications available. The framework is currently available as a support library in a temporary Jitpack repository. I guess thatâs not going to be the final location for this library in the future. - Using the Trusted Web Activity manually. If you have experience developing Android apps with Java or Kotlin, you can just plug your PWA manually into your app. That means you can have some native activities and at one point you can open the Trusted Web Activity with your PWA. In this case, I suggest analyzing the Support Library to understand how to connect to Chrome from your project.
*UPDATE 2/5: There is now available documentation in the Android website regarding TrustedWebUtils, the TWA Helper.
Spreading the Manifest #
A PWA in the App Store wonât use the Web App Manifest for defining how your app runs; we will need to copy some of those values manually. Icons will be taken from the âresâ folder like any other native Android App, orientation lock should be defined in AndroidManifestâs activity entry, etc.
If you are using the Java Support library, a splash screen might be created for you automatically but other properties from the manifest wonât be used. In fact, in my testing, I couldnât see the theme-color being applied yet when my PWA is on the screen.
URL Validation #
TWAs will work only if we digital handshake our domain with our app. This is a mechanism known as Digital Assets Links. That will make a trusted relationship between your host and your APK, proving that you are the owner of the PWA and that you wonât be publishing PWAs in the Play Store that you donât own. It also makes a digital link between your website and your native app that in theory can let them share private data (but doesnât seem to be possible with todayâs TWA API).
With Digital Asset Links you must serve under your PWAâs domain a file in the URL
If you donât do the handshake, TWAs wonât be activated and your app will just use normal Chrome Custom Tabs with a Chrome user interface similar to when your PWA has display: minimal-ui. Iâm not completely sure but I guess the Play Store might reject apps that are just pointing to normal Custom Tabs and not validated TWAs. Iâm not completely sure yet when Chrome is doing the Digital Asset Link check; if itâs being done on every access to the app before opening it as a TWA it might be a performance problem. I guess a cache will be possible, and also the Play Store might check this before accepting the app. Weâll see if future documentation gives us clarity on this matter.
There is a (not so simple) mechanism to bypass the Digital Asset Link certification process for development purposes, explained below in this article.
Publishing your App #
To publish your PWA shortcut using TWAs you will need to follow all the Google Play Store rules. Check the Developer Policy Center for more information. You will also need a Developer Publisher account paying a one-time fee of USD $25 and create metadata, screenshots and marketing material for your app.
To publish in the Google Play Store you must accept developer agreement and pay a one time USD $25 registration fee
Deployment #
When you are done creating your APK (Android Native Package) from Android Studio and you already have a Developer Console account, you must create a production APK and sign it with a self-created key that you create within Android Studio tools. You might also want to check App Signing by Google Play to simplify the process in the future.
The Google Play Console #
There are no special rules or processes to upload these apps to the Play Store, but the Revision team might detect that you are using TWAs and will do a check that 1) Digital Assets Link is enabled and validated, and 2) the URL is passing the PWA criteria (mostly for a Service Worker fetch event handler).
Filling a lot of metadata and graphic assets will be mandatory for publishing your PWA in the Google Play Store
Updating your App #
You donât need to upload your app again if you change web content â unless you change the app completely as per the store rules. You will continue updating your app through Service Workers and new deploys to your server. You will have to create and upload another APK only if you want to change metadata, native code, or icons.
Limitations #
Iâm seeing a list of possible limitations regarding the platform today, but itâs just a start and I hope we will see improvements over new versions.
PWAs in Subfolders #
If you publish your PWA in a subfolder of a host, it seems to be a couple of issues here.
- Digital Asset Link connects the whole domain, not just a folder
- The current Support Library seems to handle as an Intent (Link Capturing) the whole host, even if your PWA is in a subfolder
No internal apps #
While this is a restriction of the Play Store itself (you canât publish intranet apps, or apps that are just for you or your company), you might want to use TWAs and create APKs that you will deploy outside of the store.
That wonât be possible as Digital Asset Link works only with public URLs because Chrome needs to verify we own the domain, and thatâs is not possible with internal URLs yet.
First Load experience #
The first time you open the recently installed app, you donât have any actual files from your app (Service Worker wasnât registered yet â unless, the user visited the PWA before), so if you are offline you will end up with a blank white screen. I think trying to warm up Chrome after installation somehow will be useful in future versions. If you are using TWA APIs instead of the Support Library you might be able to detect this situation and inform the user properly using native APIs.
Calling native code #
There is already a bi-directional channel to communicate the TWA Server (Chrome) and the TWA Client (our APK). That channel is currently being used to send Push Messages and show them as being part of our native app and not Chrome, but nothing else yet.
There is a potential here to bridge native code and JavaScript code without too much effort and let our PWAs access native code, similar to what happens when we publish an APPX with a PWA for Microsoft Store.
Iâm seeing a future version with a way to register Java/Kotlin classes to the TWA Client so we can actually call them with a JavaScript API when our PWA is rendered in TWA mode.
Today, the only way to execute native code is to use Intents to open other native Activities and back opening TWA sending and receiving arguments through URIs parameters.
Also, you can create some kind of web server, or WebSocket server in native code running on a Service and let the PWA talk to it, but itâs kind of weird, complicated and maybe battery consuming. But there is a whole new world that might open now. Letâs see what the community creates!
Monetization with the Play Store #
If your app is not free to download, there will be no easy way to validate that the user has actually paid for it (at the end, your content is just a URL); also if you have digital assets or subscriptions that youâd like to sell using the Play Store wallet, it will be a challenge to make it work without having an actual bridge to native code.
Debugging #
Iâm not sure if itâs a bug or something on my development environment but remote debugging the Service Worker from the TWA is not working. I can inspect the windowâs context, but not the Service Worker.
Other engines #
TWAs work only with Chrome today, but the API might be also cloned by other browsers, such as Samsung Internet, Edge or Firefox in the future.
*UPDATE 2/4: The TWA works over the Android Custom Tab protocol that other browsers are currently implementing, so if the user doesnât have Chrome or has changed the default browser, another browser might take precedence and open the TWA with the PWA content. More testing is needed to understand how it works.
What happens if the user has an older version of Chrome and installs the app from the Play Store? In this case, your PWA will appear as a Chrome Custom Tab, not in a completely standalone mode.
Google Maps Go in the Play Store was already using something similar to TWA specifying Chrome as a requirement
What happens if the user doesnât have Chrome at all? As of today using the Support Library, your app wonât work at all (unless there is another browser listening to the Custom Tabs protocol). If you are using the TWA API on your own Java/Kotlin code you might be able to detect browser availability and load an alternate solution, such as a WebView or opening the browser.
While itâs not so common to see Android devices without Chrome, there are some devices without it by default, including new devices in Europe shipping without Chrome by default.
Other platforms #
PWAs wonât work on wear OS (watches), but Iâm not completely sure what happens on other Android platforms. I will guess a probably not yet, but Iâll test it for a next article. Iâm talking about Android TV or even Chromebooks with Play Store. In the meantime, if you didnât test it, it might be a good idea to disable those platforms in your store listing.
Conflicting with WebAPK #
If you already installed the PWA from Chrome, you already have installed an APK for that URL signed by the Play Store, but that wonât stop the store to list your App and let the user also install it. The same on the other way: having the app installed from the store wonât stop Chrome to offer the user to âAddâ it from the browser. I think this might be avoided in the future if the WebAPK also has a Digital Asset Link somehow, or if we can match WebAPKâs appâs id, but I donât see this happening soon. Weâll see.
Two Starbucks Apps running at the same time: WebAPK and our own APK
You can stop Chrome to offer WebAPK and offer your store listing app instead by using the related_applications attribute and prefer_related_applications Web App Manifestâs attributes. Get Installed Related Apps API might help in the future with this conflict.
Detecting a Trusted Web Activity (*UPDATE 2/7) #
If for some reason, you want to detect if the user is on a TWA there are two ways:
- Add an argument to the start URL the TWA will load
- Use the Referrer: On the first navigation page load in a TWA, document.referrer will be set as android-app://
; the same value will also be set as well in the HTTP Header Referer (misspelled in the HTTP spec)
Creating your first PWApk #
Yes, I know, Iâve just invented the PWApk word, but it doesnât sound too bad, right?
This article is an introduction and Iâm working in a tutorial series, so if you are interested in that, follow me on Twitter or subscribe to my newsletter.
A few years ago I did a video course on Native Web Apps for Android, that while not exactly what you need to do for PWAs, it will help web developers understand the Android ecosystem.
The simplest way to make a TWA-based APK is to clone the SVGOMG repository sample from ChromeLabs GitHub repository
You can clone the git repository or start a new project.
In our case, we will start a new project just to understand and explain whatâs going on with the solution.
Create a new Project in Android Studio and select âNo Activityâ as we will use just a Trusted Web Activity provided by the Support Library.
We start with an empty project
Fill the details, picking a name (we will override this later), and a Package name. The package name is important as it will be the ID of our app in the Android OS and also within the store. I recommend using your PWAâs host in reserve order and an optional name after, such as: com.mypwa.calculator if your PWA is https://mypwa.com/calculator
API 19 (Android 4.4) as a base looks good, as it seems that is going to be the minimum version required for Chrome soon. Some things on TWA will work only from API 23 (Android 6.0) but the Support Library will take care of that.
*UPDATE 2/5: Chrome formally announced that TWAs work only from Android 4.4 KitKat. There is around 5% of active Android users that wonât have the feature and they will fall back to a Custom Tab experience with a URL bar.
Picking the minimum API level will limit the devices that will see our PWA in the Google Play Store
Adding Dependency #
The next step is to add the TWA Support Library as a dependency, so we will go and open two files with the name build.gradle
There are two gradle configuration files, one for the project and one for the Android app
Starting with the Project build.gradle, we will add under allprojects > repositories, the following line:
maven { url **"https://jitpack.io"** }
Next step, we open the Module build.gradle and we add under dependencies:
implementation **'com.github.GoogleChrome:custom-tabs-client:e446d08014'**
Configuring the TWA #
The next step is to stay under the Moduleâs build.gradle file and setup the PWA settings for the Trusted Web Activity, under defaultConfig we will add:
manifestPlaceholders =\[
hostName: "**app.starbucks.com**",
defaultUrl: "**https://app.starbucks.com**",
launcherName: "**Starbucks**",
assetStatements: '[{ "relation": ["delegate_permission/common.handle_all_urls"], ' +
'"target": {"namespace": "web", "site": "**https://app.starbucks.com**"}}]'
]
In this case, Iâll use the Starbucks PWA as an example. The assetStatements key is the one that will need information from the Digital Asset Link process. Weâll skip that part for development purposes. The property with the name launcherName should match short_name in the Web App Manifest.
Configuring the Manifest #
Android apps have their own manifest and they wonât use our Web App Manifest, that file is under app > manifests in your Android project explorer as is called AndroidManifest.xml. You will find a self-closed Application XML element there.
There, we can change the value of android:label with ${launcherName} to use the launcherName we set before in the metadata, so we will have one single source of truth for the appâs name.
The next step is to setup this file, starting with opening the
<meta-data
android:name="asset_statements"
android:value="**${assetStatements}**" />
<activity android:name="android.support.customtabs.trusted.LauncherActivity"
android:label="**${launcherName}**">
<meta-data android:name="android.support.customtabs.trusted.DEFAULT_URL"
android:value="**${defaultUrl}**" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="https"
android:host="**${hostName}**"/>
</intent-filter>
</activity>
The code below will set up the TWA using the Support Library, the Intent Filter so your app will capture links to your PWA and the Digital Asset Link. I will skip the details on whatâs going on there from an Android appâs point of view.
At this point, you will have to make Android Studio take all your changes by clicking on âSync Now.â If everything is correct, you wonât get any errors at this point.
Icon replacement #
Now our app uses just a default android icon, we should replace all the files available in app>res>mipmap in different subfolders for different pixel densities. There are two versions, square and rounded icons. Rounded icons are new in Android 7.1 and if you want to skip them remove the android:roundIcon reference in the AndroidManifest.xml.
We need to manually take icons from our Manifest and copy them in the mipmap subfolders with the right name
Theme adjustment #
Finally, we should open app/res/values/styles.xml and make some changes to the theme so it will look like a PWA:
<style name="AppTheme" parent="**Theme.AppCompat.Light.NoActionBar**">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowNoTitle">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
You can change the colors of the app from app/res/values/colors.xml but I didnât see them yet in the TWA.
If you are currently restricting orientation in your manifest, you might also want to add that restriction in the <activity>
element in the AndroidManifest.xml.
Ready to test? #
We are ready to test our PWApk, but before that, we need to set up development TWA mode for Chrome in our Android testing device or emulator (with Chrome 72+).
Setting up Chrome #
Check that you have Chrome stable version 72 and open chrome://flags. Search for âEnable command line on non-rooted devices,â and enable the flag. You will have to restart Chrome.
Next, we need to set up Chrome to bypass Digital Asset Link for the host we want to test, in our example: app.starbucks.com. (Iâm sorry Starbucks, but we love you, you know that LOL)
To change command line arguments for Chrome on Android we need to write a text file in the Androidâs file system. The simplest way to do it is through adb (android debug bridge) that has to be in the path (google that if itâs not there) and execute:
adb shell cat /data/local/tmp/chrome-command-line \_â-âdisable-digital-asset-link-verification-for-url="https://app.starbucks.com"
There is a simple bash script available in the Chromeâs sample to use if you want to.
And now, we need to restart Chrome. But not just killing the app from the multitask window. Go the Settings / Apps / Chrome and Terminate the whole process (Force Stop). I had to do this a couple of times before having it ready.
If itâs done, then every time you open chrome you will get a warning now about that flag we enabled and if you run your app from Android Studio you will finally get your PWA up and running in standalone more under your APKâs icon and name.
Conclusion #
The idea that we can now publish PWAs in the Google Play Store is really a game changer. It seems we are in the early stages of the API right now and we definitely need a higher level solution for this. I really want to see a tool to enter our PWAâs URL and get an APK from it. It wonât be simply because of the Digital Asset Link verification system. Only the Play Store can do that just by using the same WebAPK they are generating.
I was questioning if Google was approving or not TWAs, so they are removing the suspicious at least of the TWA part of the article.
Letâs take Chrome 72 TWA as the first step of a long journey!
I want to thank Paul Kinlan for his support regarding TWAs, my questions and because Iâve been pinging him almost every month about this :P