Accessibility testing.

Progressive Web Application - How to install on mobile device

Posted by Paweł Głogowski on October 29, 2019

What is a Progressive Web App?

According to recent statistics, almost 60 percent of total internet usage in the UK comes from mobile phones. Various reasons account for that, but mostly it's because accessing the web using a smartphone or tablet is very convenient, especially for specific types of applications.

If you own an internet portal, you should definitely consider allowing users to access your application via mobile devices. Of course, users can access your portal in browsers, but that is usually less convenient than a mobile application - even if your website works perfectly on mobile devices.

Building a custom application for multiple platforms is usually quite costly, and the majority of smaller companies can't afford it. That's where Progressive Web Applications (PWAs) can help. PWA generally allows you to easily convert your web application into a native application or at least something which is more or less similar to it. In this article, I'm going to show you how to add a web page to a mobile device as a Progressive Web Application.

How to build a Progressive Web Application

Your application needs to meet specific criteria:

  1. It's served over HTTPS for security purposes.
  2. Responsive web design - it needs to look well on various mobile devices.
  3. It should work even when there's no internet connection or at least show an information screen about the lost connection.
  4. It includes "manifest.json," allowing us to add a shortcut to the mobile screen.
  5. It should work well with slower connections.

Let's focus on the manifest.json file, which is required for adding your application to the device's home screen. It basically contains information about the icon's starting address. Let's take a look at the following example of manifest.json file:

{
    "name": "yourApplicationName",
    "short_name": "Name on Home Screen",
    "icons": [
        {
            "src": "icon_file_name",
            "sizes": "192x192 152x152 144x144...",
            "type": "mime_type"
        },
        {
            "src": "next_image_size",
            "sizes": "512x512",
            "type": "image/png"
        }],
    "start_url": "/start?mode=progressive",
    "display": "display type e.g standalone",
    "theme_color": "browser theme color",
    "background_color": "color_of_spash_screen eq #FFFFFF"
}
                        

Making your application usable in case of the lack of an internet connection isn't going to be a part of this article. Instead, we will focus on enabling users to install your application for both iOS and Android applications.

How to "install" your website on a mobile device

Before we begin, note the massive difference in attitudes to Progressive Web Applications between Apple and Google. In general, Google supports PWA and wants to increase its popularity, while Apple prefers that users install native apps that can be bought in the Apple App Store. However, due to the popularity of PWA, Apple began to support it from version 11.3 of iOS. Starting from version 12.2, PWA works quite well but is still not as stable and fast as on Google Chrome. Let's take a look at how to install your web application on Android phones.

First of all, you need to use Google Chrome because other browsers don't support PWA yet. Google Chrome fires the "beforeinstallprompt" event, which can be handled in a customized way. To do so, add the code shown below on a high level of the application. For a React application, that can be the App.js file.

Consider the following code:

let deferredPrompt; // Variable should be out of scope of addEventListener method

window.addEventListener('beforeinstallprompt', (e) => {
    e.preventDefault();	// This prevents default chrome prompt from appearing
                            
    deferredPrompt = e;	 // Save for later
    let infoBar = document.querySelector('#custom-info-bar');
    if (infoBar) {
        infoBar.style.display = '';
        let installBtn = document.querySelector('#custom-install-button');
                            
        installBtn.addEventListener('click', (e) => {
        //This prompt window
        deferredPrompt.prompt();
        // Here we wait for user interaction
        deferredPrompt.userChoice
            .then((choiceResult) => {
                if (choiceResult.outcome === 'accepted') {
                    let infoBar = document.querySelector('#custom-info-bar');
                    infoBar.style.display = 'none'; // Hide info bar
                    deferredPrompt = null; // not need anymore
                }
            });
        });
    }
});
                    

In the first line, you can see:

e.preventDefault();
                    

Without that, you'll see a Chrome embedded info bar with a message like "Add This App to Home Screen" along with the dismiss button. When dismissing this window, expect it to pop up once again in a couple of weeks. You may ask: why bother with a custom solution? Well, first of all, you can create your own solution - it could be an info bar, a banner, or whatever else you want. It can also be customized in terms of colors and layout. A custom solution will significantly improve the user experience. In the above example we use a snackbar to inform users about the possibility of installing the application.

On the button handler, you can see

deferredPrompt.prompt();
                        
It's basically will show a banner like this

Add to Home screen banner

Keep in mind that you should declare deferredPrompt as a global variable. If you fail to do so, the prompt window won't open once again after clicking the cancel button. I believe that the rest of the code is self-explanatory.

Also, you can easily determine if you're using PWA mode. That can be useful because you don't want to show the info bar to users who are already using the PWA. You can do it using the following code:

isInStandaloneMode = () => ('standalone' in window.navigator) && (window.navigator.standalone);
                        

Adding a PWA to the home screen in iOS

Unfortunately, accomplishing the same in iOS is far more complicated. Basically, we need to do it manually. The only thing that can be done from the application perspective is showing some kind of information on how to do it. At Solidstudio Software House, we use a snack bar widget that appears at the bottom of the application with a short instruction about how to add it to the home screen. Also, keep in mind that adding a PWA to the home screen in iOS is available only on Safari, and the event "beforeinstallprompt" isn't fired on iOS.

Add to Home screen banner

The only challenge here is determining whether the actual device is controlled by iOS. We can do it by analyzing the user agent string. Unfortunately, starting from iOS 13 we can't determine whether it's an iPhone or iPad - instead, it will always show as "Macintosh." This is tricky because we need to identify if this device is a phone or tablet since it's pointless to show the information bar on desktop devices. Also, we need to indicate if the current browser is Safari since it doesn't make sense to show that bar on other browsers than Safari. As it turns out, that's not easy because all browsers on iOS are wrappers on Safari. Consider the following examples:

// Detects if device is on iOS
isIos = () => {
    const userAgent = window.navigator.userAgent.toLowerCase();
    return /iphone|ipad|ipod|macintosh/.test(userAgent);
}
                                
// Detects if device is on iOS
isSafari = () => {
    return navigator.vendor && navigator.vendor.indexOf('Apple') > -1 &&
        navigator.userAgent &&
        navigator.userAgent.indexOf('CriOS') === -1 &&
        navigator.userAgent.indexOf('FxiOS') === -1;
}                                

We search for an iPad, iPhone string in the user agent string for the older version of the iOS system. Analyzing the user agent string, we notice that Safari agents have no references for 'CriOS' or 'FxiOS'. So in the newest version of iOS, you have to determine if the device is a mobile one. At Solidstudio, we use a simple but effective solution to determine it by the width of the screen. Since iPads has 1024 screen width, we can use the following code:

isMobile = () => {
    return window.innerWidth < 1025
}                                 
                        

Summary

It required a lot of research and developing a custom solution, but we managed to create an effective mechanism that encourages users to install applications on their mobile devices. At Solidstudio Software House, we have used the PWA technology in our project for T-Cup. We want to offer users native experience and increase engagement with the app. However, it's not the only challenge we encounter with PWA; we were also struggling with the auto-refresh of the application in standalone mode. I'm going to cover that topic in the upcoming articles, so make sure to subscribe to our newsletter!

Let`s work together!

+48 538 365 618