By
Pete LePage
Add to Home Screen on Android does more than just add the Progressive Web App to the users Home Screen. Chrome automatically generates and installs a special APK of your app. We sometimes refer to this as a WebAPK. Being installed via an APK makes it possible for your app to show up in the app launcher, in Android’s app settings and to register a set of intent filters.
To generate the WebAPK Chrome looks at the web app manifest, and other meta-data. Whenever the manifest changes, Chrome will need to generate a new APK.
Android intent filters
When a Progressive Web App is installed on Android, it will register a set of intent filters for all URLs within the scope of the app. When a user clicks on a link that is within the scope of the app, the app will be opened, rather than opening within a browser tab.
Consider the following partial manifest.json
, when launched from the app launcher, it would launch https://example.com/
as a standalone app, without any browser chrome.
"start_url": "/",
"display": "standalone",
Copy the code
The WebAPK would include the following intent filters:
<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="example.com"
android:pathPrefix="/" />
</intent-filter>
Copy the code
If the user clicks on a link within an installed app to https://example.com/read
, it would be caught by the intent and opened in the Progressive Web App.
Using scope
to restrict intent filters
If you don’t want your Progressive Web App to handle all URLs within your site, you can add the scope
property to your web app manifest. The scope
property tells Android to only open your web app if the URL matches the origin
+ scope
, and limits which URLs will be handled by your app and which should be opened in the browser. This is helpful when you have your app and other non-app content on the same domain.
Consider the following partial manifest.json
, when launched from the app launcher, it would launch https://example.com/app/
as a standalone app, without any browser chrome.
"scope": "/app/",
"start_url": "/",
"display": "standalone",
Copy the code
Like before, the generated WebAPK would include an intent filter but would modify the android:pathPrefix
attribute in the APK’s AndroidManifest.xml
:
<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="example.com"
android:pathPrefix="/app/" />
</intent-filter>
Copy the code
Let’s take a look at a few examples: https://example.com/app/ – within /app/ https://example.com/app/read/book – within /app/ https://example.com/help/ – not in /app/ https://example.com/about/ – not in /app/
See scope
for more information about scope
, what happens when you don’t set it, and how you can use it to define the scope of your app.
Managing permissions
Permissions work in the same way as other web apps and cannot be requested at install time, instead they must be requested at run time, ideally only when you really need them. For example, don’t ask for camera permission on first load, but instead wait until the user attempts to take a picture.
Managing storage and app state
Even though the progressive web app is installed via an APK, Chrome uses the current profile to store any data, and it will not be segregated away. This allows a shared experience between the browser and the installed app. Cookies are shared an active, any client side storage is accessible and the service worker is installed and ready to go.
Though, this can be an issue if the user clears their Chrome profile, or chooses to delete site data.