4

I've got a progressive web app, app.example.com created using Chrome's "Add to Home Screen" button on Android.

I have an NFC tag that ordinarily opens app.example.com/nfc_app in Chrome when it's tapped.

How can I make it so that this NFC tag opens up the app.example.com/nfc_app PWA instead of Chrome when tapped?

user1522860
  • 113
  • 1
  • 6
  • I have the same issue. When the link is selected from other websites my PWA opens, but the NFC intent opens to Chrome. Android 8 on Pixel and Android 6 on LG Pheonix 2 – Aaron Roller Nov 11 '17 at 15:11

2 Answers2

0

Add a helper application as a work-around:

package com.something;

import android.content.Intent;
import android.net.Uri;
import android.nfc.NfcAdapter;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    private void handleNfcIntent(@Nullable Intent intent) {
        if (intent != null && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            //clear the intent so it doesn't come back
            intent.setAction("");
            Uri uri = intent.getData();
            if (uri != null) {
                Intent uriOnlyIntent = new Intent(Intent.ACTION_VIEW, uri);
                //call the progressive web app registered to view the uri
                startActivity(uriOnlyIntent);
            }
        }
    }

    @Override
    protected void onNewIntent(final Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
    }

    @Override
    protected void onResume() {
        super.onResume();
        //https://stackoverflow.com/a/36942185 provided the insight for handling this way
        //always called after onNewIntent and onCreate allowing a tag reward for a closed app
        handleNfcIntent(getIntent());

    }
}

Your AndroidManifest.xml listens for your target url:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.something">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:host="something.com" android:scheme="https" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Now when you scan your tag, the NFC Intent will be handled by the installed app which forwards to the View Intent which your Progressive Web App is registered.

For me, this only worked in Android 8, not Android 6 since apparently opening a PWA by clicking on a link in Chrome is also not supported.

An unfortunate work-around so I'm hoping to see a better answer.

Aaron Roller
  • 1,074
  • 1
  • 14
  • 19
  • see Google Developer post for more information about the manifest: https://developers.google.com/web/updates/2017/02/improved-add-to-home-screen#android_intent_filters – Aaron Roller Nov 11 '17 at 17:39
0

Can confirm, Android 8, links on other websites or from other apps open the PWA just fine, but the NFC intent opens Chrome. Here is another workaround that doesn't require you to install a native helper APK:

Create a simple redirect HTML file pwa.html and serve it from a different domain, let's say other.example.com:

<html>
    <body><a id="link"></a></body>
    <script type="text/javascript">
        var a = document.getElementById('link');
        // set the target link as desired, may add routes and params etc.
        a.href = "https://app.example.com/...";
        a.click();
    </script>
</html>

Then, instead of having the NFC tag point to https://app.example.com, you would program it to point to your redirect HTML https://other.example.com/pwa.html. It's not perfect and really just a workaround, but simpler than building and installing a separate APK.

potpiejimmy
  • 221
  • 2
  • 6
  • Is there a reason you need a separate HTML file (pwa.html) AND additionally a diffent subdomain? wouldn't it be sufficient to put https//app.example.com/pwa.html to the tag ? – ErikM Jun 11 '18 at 07:46
  • No, unfortunately not, you need to serve the pwa.html from a different domain, otherwise Chrome is opened in the context of the app.example.com domain and then when evaluating the link Chrome won't open the PWA because it thinks that - since you're already browsing the target domain in the browser - you don't want it to leave the browser (because the link points to a page in the same domain). – potpiejimmy Jun 25 '18 at 21:47
  • I assume it also doesn't work when you link the NFC tag to an webservice that returns a redirect (http: 302), correct ? – ErikM Jun 26 '18 at 19:21