21

I've created a mobile-friendly web site with jQuery Mobile and added some meta info so that it should be pinned to iOS and Android homescreens and should be launched as a web app (in other words: in a browser, but without browser navigation elements).

It works fine for iOS, but it doesn't work for Android 4.4.2.

I followed this tutorial for creating Android-Compatible web apps:

Despite adding all the meta info as listed in the tutorial, Android does show the "Add to homescreen" button for my web site, but it does not launch the website without browser navigation elements as described in the tutorial.

What am I doing wrong?

Sam Denty
  • 3,693
  • 3
  • 30
  • 43
Adrian Grigore
  • 33,034
  • 36
  • 130
  • 210
  • 1
    The availability of "Add to homescreen" does not depend on your website, but rather on Google Chrome. Please try to test with the latest version of Chrome. – ozbek Jan 17 '14 at 01:55
  • @shoe rat: I am using the lastest Chrome version (32.0.1700.99 on Android 4.2.2 / Nexus 7) – Adrian Grigore Jan 20 '14 at 15:47
  • Is [this](https://lh3.googleusercontent.com/-kCtJvWxs-d0/Ut1QUXv9gYI/AAAAAAAAKeg/AI1aBmNJt4o/w1080-h1920-no/Screenshot_2014-01-21-01-29-03.png) not what you are looking for? – ozbek Jan 20 '14 at 16:42
  • @shoe rat: It is now, but when I launch the link on my device the browser bar is not gone, as it should be a for a properly configured web app. – Adrian Grigore Jan 20 '14 at 21:03

3 Answers3

40

As you can see here this feature is still tagged as Beta. I guess you'll need to test this feature with the latest version of Chrome. From the article:

Supporting add to homescreen apps

Chrome will look for the following meta tag in the element of the web-page:

<meta name="mobile-web-app-capable" content="yes">

The name attribute MUST be "mobile-web-app-capable" and the content attribute must be "yes" (case in-sensitive). If there is any other value in the content attribute the web app will be added as a regular bookmark.

Icon

The icon that is used to install to the homescreen is determined by using the largest icon found in one of the following <link> tags:

<link rel="shortcut icon" sizes="192x192" href="nice-highres.png"> (recommended)
<link rel="shortcut icon" sizes="128x128" href="niceicon.png">
<link rel="apple-touch-icon" sizes="128x128" href="niceicon.png">
<link rel="apple-touch-icon-precomposed" sizes="128x128" href="niceicon.png">

Caution: The 192px image format is recommended. The last two formats (apple-touch-*) are deprecated, and will be supported only for a short time.

Icon label

The application’s <title> element serves as the default label for the icon on the homescreen.

Configuration

The following example is the minimum required configuration to support a homescreen launch experience.

<!doctype html>
<html>
   <head>
     <title>Awesome app</title>
     <meta name="viewport" content="width=device-width">
     <meta name="mobile-web-app-capable" content="yes">
     <link rel="shortcut icon" sizes="192x192" href="/icon.png">
   </head>
   <body></body>
</html>

Comparison to iOS Safari Add to Homescreen

Chrome will also allow Web Apps to launch in "App mode" if they embed a meta tag using the "apple-mobile-web-app-capable" name. Chrome will stop supporting this usage in an upcoming release. Chrome currently shows a deprecation warning in the Developer Tools’ console log when it detects a page with only the "apple-mobile-web-app-capable" meta tag. The warning appears as follows:

Android vs iOS

Whilst Chrome temporarily accepts the usage of "apple-mobile-web-app-capable", Chrome does not offer compatibility with the iOS Safari API’s including:

window.navigator.standalone
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-startup-image" href="/startup.png">

I hope it helps.

Mrtn
  • 107
  • 5
Assaf Gamliel
  • 11,935
  • 5
  • 41
  • 56
  • 1
    Thanks for your reply, but I *am* using the latest chrome version (32.0.1700.99 on Android 4.2.2 / Nexus 7) and you are merely quoting from the article that I already linked in my question, without providing any new information. – Adrian Grigore Jan 20 '14 at 15:46
  • Well, I use Nexus 5 with 4.4.2 and your site works perfectly for me. Loading exactly as you intended. I will try to get my hands on a Nexus 7 with 4.2.2 and let you know what I figured out. Maybe I have a device with 4.2.2 laying around here somewhere. Sorry if the answer wasn't to your liking, I thought following Google's doc will be better to other people reading your question too as the implementation might change in the future. As I said, I'll try to report back as soon as I can. Best of luck mean while. – Assaf Gamliel Jan 21 '14 at 07:52
  • 2
    Thanks for your follow-up! Just to make sure: do you mean that the site loads from Homescreen in your Nexus 5 without showing the browser navigation Elements? – Adrian Grigore Jan 22 '14 at 14:48
  • @AdrianGrigore Correct, just like you'd expect, it loads in full screen mode. – Assaf Gamliel Jan 22 '14 at 15:34
  • Ok, In that case it seems to be my Nexus 7's fault. Thanks for helping me! :-) – Adrian Grigore Jan 22 '14 at 17:56
  • 3
    According to the android docs, this solution is now out of date. See: https://developers.google.com/web/fundamentals/engage-and-retain/app-install-banners/ – marcovtwout May 09 '17 at 11:55
0

The guide indicates that as of Chrome 68 it is expected that the app developer adds a button to their app. And that it should only work if the PWA criteria are met. Then you should be able to use the following code to get a callback to your app where you can show a button to the user to kick off the Add to home screen prompt.

Per the guide, add this listener.

let deferredPrompt;

window.addEventListener('beforeinstallprompt', (e) => {
  // Prevent Chrome 67 and earlier from automatically showing the prompt
  e.preventDefault();
  // Stash the event so it can be triggered later.
  deferredPrompt = e;
  // Update UI notify the user they can add to home screen
  btnAdd.style.display = 'block';
});

Then.... the user needs to click the button, after which you can run this code.

btnAdd.addEventListener('click', (e) => {
  // hide our user interface that shows our A2HS button
  btnAdd.style.display = 'none';
  // Show the prompt
  deferredPrompt.prompt();
  // Wait for the user to respond to the prompt
  deferredPrompt.userChoice
    .then((choiceResult) => {
      if (choiceResult.outcome === 'accepted') {
        console.log('User accepted the A2HS prompt');
      } else {
        console.log('User dismissed the A2HS prompt');
      }
      deferredPrompt = null;
    });
});

I converted this to a react component fairly easily, the code below is cut down from my Redux project, so it will not work copy/paste, but should give the general idea.

import React, { Component } from 'react'
import Button from '@material-ui/core/Button'

class AddToHomeScreen extends Component {
  constructor (props) {
    super(props)
    this.deferredPrompt = null
    this.state = {
      show: false
    }
  }

  componentDidMount () {
    var component = this
    window.addEventListener('beforeinstallprompt', e => {
      // Prevent Chrome 67 and earlier from automatically showing the prompt
      e.preventDefault()
      // Stash the event so it can be triggered later.
      component.deferredPrompt = e
      // Show button
      console.log('beforeinstallprompt triggered... show add button')
      component.setState({ show: true })
    })
  }

  // bind to this
  handleAddClick () {
    if (this.deferredPrompt) {
      this.setState({ show: false })
      // Show the prompt
      this.deferredPrompt.prompt()
      // Wait for the user to respond to the prompt
      this.deferredPrompt.userChoice.then(choiceResult => {
        if (choiceResult.outcome === 'accepted') {
          console.log('User accepted the A2HS prompt')
        } else {
          console.log('User dismissed the A2HS prompt')
        }
        this.deferredPrompt = null
      })
    } else {
      console.log('Invalid prompt object')
    }
  }

  render () {
    const { show } = this.state
    if (!show) return null

    return (
      <div className={classes.root}>
        <Button variant="contained" onClick={this.handleAddClick.bind(this)}>
          Add to home screen
        </Button>
      </div>
    )
  }
}

export default AddToHomeScreen

References: https://developers.google.com/web/fundamentals/app-install-banners/

Simon Hutchison
  • 2,949
  • 1
  • 33
  • 32
0

<link rel="manifest" href="/manifest.json">

Contents of the manifest.json:


    {
      "name": "Your Website Name",
      "short_name": "Short Name",
      "icons": [
        {
          "src": "/path/to/icon.png",
          "sizes": "192x192",
          "type": "image/png"
        }
      ],
      "start_url": "/",
      "display": "standalone",
      "background_color": "#ffffff",
      "theme_color": "#000000"
    }

And then you can play with different values for the "display" property, for me "standalone" activated the "Install app" button, but "display" value actually was what I needed to see the "Add to home screen" button. Cheers..

the_root
  • 329
  • 3
  • 9