Vapor Trail

明るく楽しく元気よく

QRコードでのアプリ起動とユニバーサルリンク

QRコードを読み込んでアプリがインストール済みの場合はアプリを起動し、未インストールのときはストアもしくは特定のURLをブラウザで開くようにしたい。

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="apple-mobile-web-app-capable" content="yes"/>
    <title>Starting App...</title>
    <script>

        var URL = "example-app://~~"; //Android 起動して表示したいアプリのページ
        var MARKET = "market://details?id=com.example";
        var iTunes = "itms://itunes.apple.com/app/idxxxxxxx";
        var QR = "http://example.com/qr";
        var UniversalLink = "https://example.com/app-page"; //iOS 起動して表示したいアプリのページ

        function onLoad() {
            if (navigator.userAgent.match(/Android/)) {
                if (navigator.userAgent.match(/Chrome/)) {
                    setTimeout(function () {
                        if (!document.webkitHidden)
                            window.location.href = MARKET;
                    }, 1000);
                    window.location.href = URL;
                } else {
                    var iframe = document.createElement("iframe");
                    iframe.style.border = "none";
                    iframe.style.width = "1px";
                    iframe.style.height = "1px";
                    var t = setTimeout(function () {
                        window.location = MARKET;
                    }, 1000);
                    iframe.onload = function () {
                        clearTimeout(t)
                    };
                    iframe.src = URL;
                    document.body.appendChild(iframe);
                }
            } else if (navigator.userAgent.match(/iPhone|iPad|iPod/)) {
                setTimeout(function () {
                    if (!document.webkitHidden) {
                        window.location = iTunes;
                    }
                }, 25);
                window.location = UniversalLink;
            } else {
                // PCで開いた場合はQRコードを表示
                var img = document.createElement("img");
                img.src = "https://chart.googleapis.com/chart?chs=300x300&cht=qr&chl=" + encodeURIComponent(QR);
                document.body.appendChild(img);
            }
        }
    </script>
</head>
<body onload="onLoad()">
</body>
</html>

ios - How to fall back to marketplace when Android custom URL scheme not handled? - Stack Overflow を参考にQRコード読み込み先のページに上記のhtmlを設置した。

  1. QRコードを読み込み
  2. ブラウザが起動して、上記のHTMLを読み込み
    2-1. アプリインストール済みの場合はアプリが起動
    2-2. アプリ未インストールの時はストアページが開く

Androidは上記の処理で問題なく動いたが、iOSのユニバーサルリンクはリンク元とリンク先が同一ドメインだと使えないという罠があった。

ユニバーサルリンクはリンクを開いた時にインストール済みのアプリが起動する仕組み。 リンクをクリックすると https://リンク先.com/apple-app-site-association 1 に設定してあるリンクのpathに対応してAssociatedDomainsのリンクに登録されたアプリが起動する。

たとえばAssociatedDomainsにapplinks:example.comと設定されたアプリをインストールしてAというサイトでexample.comのリンクを踏むとhttps://example.com/apple-app-site-association の設定をもとにアプリが起動する。
下記の例はpathsを"*"に設定してexample.comのどのパスでも起動するようにしているが、URLに特定のパスが含まれるときのみアプリを起動させたりすることもできる 2

apple-app-site-association.json

{
    "applinks": {
        "apps": [],
        "details": {
            "チーム名.com.example": {
                "paths": [
                    "*"
                ]
            }
        }
    }
}

ただiOSの場合はリンク元ドメインとリンク先のドメインが同一だと起動しない仕組みになっており、example.com内のページをSafariで閲覧中にexample.com/~~のリンクを踏んでもアプリは起動しない。

When a user is browsing your website in Safari and they tap a universal link to a URL in the same domain as the current webpage, iOS respects the user’s most likely intent and opens the link in Safari. If the user taps a universal link to a URL in a different domain, iOS opens the link in your app.
ユーザーがSafariでWebサイトを閲覧しているときに、現在のWebページと同じドメインのURLへのユニバーサルリンクをタップすると、iOSはユーザーの最も可能性の高い意図を尊重し、Safariでリンクを開きます。ユーザーが別のドメインのURLへのユニバーサルリンクをタップすると、iOSはアプリでリンクを開きます。

App Search Programming Guide: Support Universal Links

普段iPhoneを使用していないので知らない挙動だったが、ブラウザで閲覧中にURLをタップしても勝手に外部アプリが起動しないようにという配慮らしい。

今回の場合QRコードの読み込み先としてhttps://example.com/~~にアクセスさせて、さらにユニバーサルリンクとして設定したhttps://example.com/app-page にリダイレクトしてアプリを起動するはずだったが、リダイレクト元とリダイレクト先のドメインが同一なのでアプリが起動しなかった。

そのためサブドメインを使用してAssociatedDomainsに設定しているapplinksをexample.comからsub.example.comに変更し、apple-app-site-associationはhttps://sub.example.com/apple-app-site-associatioに設置。 QRコードの読み込み先URLはhttps://example.com/~~ に設置しておいて、https://sub.example.com にリダイレクトさせるようにした。ややこしい。

参考: [Swift] 同一ドメインでのユニバーサルリンク(Universal Links)は動作しないので注意 - Qiita


  1. アプリインストールor更新時にダウンロードされるらしい。https://developer.apple.com/forums/thread/6972

  2. メルカリの設定例: https://www.mercari.com/apple-app-site-association