23 June 2023

How To: Implement an Android Smart App Banner

webdev android

So there isn’t an Android Smart App Banner like the one for iOS but there is the Native App Install Prompt, which is about as much as we get natively on Android. Sorry for the bait-and-switch, there…

It looks like this.

Native App Install Prompt Banner

Tapping the banner brings up a dialog like this.

Native App Install Prompt Dialog

Tapping install in that dialog takes you to the Play Store.

So, How Do You Implement It?

Unfortunately, the documentation for the prompt isn’t very good. It skips over important information and talks about a very similar prompt for PWAs without ever clarifying which bits matter to what prompts.

To get this banner working for Native Android Apps all you have to do is add a manifest file with the following properties:

You then have to ensure that the manifest is declared in your HTML.

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

That’s it, the prompt will now show up. You don’t need to listen for events or show buttons or anything. I repeat:

All you need to do to get the banner to show up is to add a manifest file with the required properties.

Example

{
  "short_name": "Cool App",
  "name": "Cool App - You're going to love it",
  "icons": [
    {
      "src": "/android-chrome-192x192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "/android-chrome-512x512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "prefer_related_applications": true,
  "related_applications": [
    {
      "platform": "play",
      "id": "com.example.cool_app"
    }
  ]
}

I Don’t See the Prompt

Unfortunately, even if you do this, the prompt still will not likely show up. As noted in the documentation, there are several other factors that Chrome uses before it will trigger the prompt. This includes:

These requirements can make testing whether you’ve set up your manifest correctly quite difficult. Fortunately, there are a couple of Chrome flags you can use to make things easier.

Bypass User Engagement Checks

If you enable #bypass-app-banner-engagement-checks, then the banner will show up on the first (and every) visit to your site, as long as the other criteria are met.

Insecure Origins Treated As Secure

Since you need to be on a mobile device, it might be hard to visit your site running in local development mode without paying for a service like ngrok. On Mac OS, at least, you can visit your site running locally from a mobile device on the same WiFi network by simply visiting the IP for your Mac (found in the wifi settings panel). You can then tell Chrome to treat that IP address as secure by adding it to the #unsafely-treat-insecure-origin-as-secure flag.

Advanced Usage

You don’t have to serve your manifest file as a static file. If you want to make use of asset helpers or translations, you can back your manifest file with an endpoint. This example is ruby based, but the same approach works wherever.

<link rel="manifest" href="/webapp_manifest" />
# routes.rb
resource :webapp_manifest, only: :show

# app/controllers/webapp_manifests_controller.rb
class WebappManifestsController
  def show
    render json: {
      name: I18n.t("long_app_name"),
      short_name: I18n.t("short_app_name"),
      prefer_related_applications: true,
      related_applications: {
        id: AppIds::PLAY_STORE_APP_ID,
        platform: "play"
      },
      icons: [
        {
          src: asset_url("app_store_icon_512")
          type: "image/png",
          sizes: "512x512"
        },
        {
          src: asset_url("app_store_icon_192")
          type: "image/png",
          sizes: "192x192"
        },
      ]
    }
  end
end

Conclusion

I hope you find this post useful and less confusing than the official documentation.

I’ve now implemented this for three different sites for three different companies over the last 5 years and each time I wished for a post like this.

So, this time, I wrote it down. This has mainly been for me more than anything 😉