web-dev-qa-db-ja.com

iPhoneのWebページからアプリがインストールされているかどうかを確認する方法

IPhoneにアプリケーションがインストールされていない場合にiPhoneをアプリストアにリダイレクトするページであるWebページを作成しますが、iPhoneにアプリケーションがインストールされている場合は、アプリケーションを開きます。

IPhoneアプリケーションにカスタムURLを既に実装しているため、アプリケーションのURLは次のようになります。

myapp://

このURLが無効な場合、ページをアプリストアにリダイレクトする必要があります。これはまったく可能ですか?

電話にアプリケーションをインストールしておらず、safariでmyapp:// URLを記述すると、エラーメッセージのみが表示されます。

Javascriptにいハックがあったとしても、本当に知りたいですか?

129
Joakim Engstrom

私が知る限り、ブラウザからアプリがインストールされているかどうかを確認することはできません。

ただし、電話をアプリにリダイレクトしてみてください。何も起こらない場合は、次のように指定したページに電話をリダイレクトします。

setTimeout(function () { window.location = "https://iTunes.Apple.com/appdir"; }, 25);
window.location = "appname://";

コードの2行目で結果が得られた場合、最初の行は実行されません。

お役に立てれば!

同様の質問:

174
missemisa

受け入れられた答えをさらに進めるために、アプリを起動した後にブラウザを返すユーザーを処理するためのコードを追加する必要がある場合があります。setTimeout関数は実行するたびに実行されます。だから、私はこのようなことをします:

var now = new Date().valueOf();
setTimeout(function () {
    if (new Date().valueOf() - now > 100) return;
    window.location = "https://iTunes.Apple.com/appdir";
}, 25);
window.location = "appname://";

そのようにして、コードの実行(つまり、アプリの切り替え)がフリーズした場合、実行されません。

144
Alastair

iOS Safariには、アプリ(インストールされている場合)またはApp StoreにリンクするWebページに「スマート」バナーを追加できる機能があります。

これを行うには、metaタグをページに追加します。アプリの読み込み時に何か特別なことをしたい場合は、詳細なアプリURLを指定することもできます。

詳細は、Appleの Smart App Bannerを使用したアプリのプロモーション ページにあります。

このメカニズムには、簡単で標準化されたバナーを表示できるという利点があります。欠点は、見た目や場所をあまり制御できないことです。また、ページがSafari以外のブラウザーで表示される場合、すべてのベットはオフになります。

27
brainjam

@Alistairは この回答 で、ユーザーがアプリを開いた後にブラウザに戻ることがあると指摘しました。その回答に対するコメント者は、iOSのバージョンに応じて、使用する値を変更する必要があることを示しました。私たちのチームがこれに対処しなければならなかったとき、最初のタイムアウトの時間値とブラウザに戻ったかどうかを示す時間値を調整する必要があり、すべてのユーザーとデバイスでうまくいかないことがよくありました。

任意の時間差のしきい値を使用してブラウザに戻ったかどうかを判断するのではなく、「pagehide」および「pageshow」イベントを検出することは理にかなっています。

次のWebページを作成して、何が起こっているかを診断しました。主にコンソールロギング、アラート、Web Inspector、jsfiddle.netなどの技術を使用すると、すべてこのワークフローに欠点があるため、イベントの展開時にHTML診断が追加されます。時間のしきい値を使用するのではなく、Javascriptは「pagehide」イベントと「pageshow」イベントの数をカウントして、それらが発生したかどうかを確認します。そして、最も堅牢な戦略は、(他の人によって報告/提案された25、50、または100ではなく)1000の初期タイムアウトを使用することであることがわかりました。

これは、ローカルサーバーで提供できます。 python -m SimpleHTTPServerおよびiOS Safariで表示。

プレイするには、「インストール済みアプリを開く」または「アプリがインストールされていない」リンクを押します。これらのリンクにより、それぞれマップアプリまたはApp Storeが開きます。その後、Safariに戻って、イベントのシーケンスとタイミングを確認できます。

(注:これはSafariでのみ機能します。他のブラウザー(Chromeなど)の場合、pagehide/show-equivalentイベントのハンドラーをインストールする必要があります)。

更新:@Mikkoがコメントで指摘したように、使用しているpageshow/pagehideイベントはiOS8ではサポートされていないようです。

<html>
<head>
</head>
<body>
<a href="maps://" onclick="clickHandler()">Open an installed app</a>
<br/><br/>
<a href="xmapsx://" onclick="clickHandler()">App not installed</a>
<br/>

<script>

var hideShowCount = 0 ;
window.addEventListener("pagehide", function() {
    hideShowCount++ ;
    showEventTime('pagehide') ;
});

window.addEventListener("pageshow", function() {
    hideShowCount++ ;
    showEventTime('pageshow') ;
});

function clickHandler(){
    var hideShowCountAtClick = hideShowCount ;
    showEventTime('click') ;
    setTimeout(function () {
               showEventTime('timeout function '+(hideShowCount-hideShowCountAtClick)+' hide/show events') ;
               if (hideShowCount == hideShowCountAtClick){
                    // app is not installed, go to App Store
                    window.location = 'http://iTunes.Apple.com/app' ;
               }
            }, 1000);
}

function currentTime()
{
    return Date.now()/1000 ;
}

function showEventTime(event){
    var time = currentTime() ;
    document.body.appendChild(document.createElement('br'));
    document.body.appendChild(document.createTextNode(time+' '+event));
}
</script>
</body>
</html>
9
brainjam

2017年の時点では、アプリがインストールされていることを検出する信頼性の高い方法はないようで、リダイレクトトリックはどこでも機能しません。

電子メールから直接ディープリンクする必要がある(非常に一般的な)私のような人にとっては、次のことに注意する価値があります。

  • Gmailでリンクがフィルタリングされるため、appScheme://を使用してメールを送信しても正常に機能しません。

  • AppScheme://への自動リダイレクトはChromeによってブロックされます:Chromeはリダイレクトとユーザーインタラクション(クリックなど)を同期させる必要があると思われます

  • AppScheme://を使用せずにディープリンクできるようになりましたが、最新のプラットフォームと追加のセットアップが必要になります。 AndroidiOS


他の人がすでにこれについて深く考えていることは注目に値します。 Slackが彼の「マジックリンク」機能をどのように実装するかを見ると、次のことがわかります。

  • 通常のhttpリンクを含むメールを送信します(Gmailでは問題ありません)
  • WebページにはappScheme://にリンクする大きなボタンがあります(Chromeでは問題ありません)
9

問題を解決しようとするこのプラグインをチェックアウトできます。 missemisaやAlastairなどで説明されているものと同じアプローチに基づいていますが、代わりに非表示のiframeを使用します。

https://github.com/hampusohlsson/browser-deeplink

9
hampusohlsson

私はこのようなことをする必要があり、私は次の解決策に行き着きました。

2つのボタンがあるページを開く特定のWebサイトのURLがあります

1)ボタン1はWebサイトに移動します

2)ボタン2でアプリケーションに移動(iphone/Android電話/タブレット)アプリがインストールされていない場合(別のURLやアプリストアなど)、ここからデフォルトの場所にフォールバックできます

3)ユーザーの選択を記憶するクッキー

<head>
<title>Mobile Router Example </title>


<script type="text/javascript">
    function set_cookie(name,value)
    {
       // js code to write cookie
    }
    function read_cookie(name) {
       // jsCode to read cookie
    }

    function goToApp(appLocation) {
        setTimeout(function() {
            window.location = appLocation;
              //this is a fallback if the app is not installed. Could direct to an app store or a website telling user how to get app


        }, 25);
        window.location = "custom-uri://AppShouldListenForThis";
    }

    function goToWeb(webLocation) {
        window.location = webLocation;
    }

    if (readCookie('appLinkIgnoreWeb') == 'true' ) {
        goToWeb('http://somewebsite');

    }
    else if (readCookie('appLinkIgnoreApp') == 'true') {
        goToApp('http://fallbackLocation');
    }



</script>
</head>
<body>


<div class="iphone_table_padding">
<table border="0" cellspacing="0" cellpadding="0" style="width:100%;">
    <tr>
        <td class="iphone_table_leftRight">&nbsp;</td>
        <td>
            <!-- INTRO -->
            <span class="iphone_copy_intro">Check out our new app or go to website</span>
        </td>
        <td class="iphone_table_leftRight">&nbsp;</td>
    </tr>
    <tr>
        <td class="iphone_table_leftRight">&nbsp;</td>
        <td>
            <div class="iphone_btn_padding">

                <!-- GET IPHONE APP BTN -->
                <table border="0" cellspacing="0" cellpadding="0" class="iphone_btn" onclick="set_cookie('appLinkIgnoreApp',document.getElementById('chkDontShow').checked);goToApp('http://getappfallback')">
                    <tr>
                        <td class="iphone_btn_on_left">&nbsp;</td>
                        <td class="iphone_btn_on_mid">
                            <span class="iphone_copy_btn">
                                Get The Mobile Applications
                            </span>
                        </td>
                        <td class="iphone_btn_on_right">&nbsp;</td>
                    </tr>
                </table>

            </div>
        </td>
        <td class="iphone_table_leftRight">&nbsp;</td>
    </tr>
    <tr>
        <td class="iphone_table_leftRight">&nbsp;</td>
        <td>
            <div class="iphone_btn_padding">

                <table border="0" cellspacing="0" cellpadding="0" class="iphone_btn"  onclick="set_cookie('appLinkIgnoreWeb',document.getElementById('chkDontShow').checked);goToWeb('http://www.website.com')">
                    <tr>
                        <td class="iphone_btn_left">&nbsp;</td>
                        <td class="iphone_btn_mid">
                            <span class="iphone_copy_btn">
                                Visit Website.com
                            </span>
                        </td>
                        <td class="iphone_btn_right">&nbsp;</td>
                    </tr>
                </table>

            </div>
        </td>
        <td class="iphone_table_leftRight">&nbsp;</td>
    </tr>
    <tr>
        <td class="iphone_table_leftRight">&nbsp;</td>
        <td>
            <div class="iphone_chk_padding">

                <!-- CHECK BOX -->
                <table border="0" cellspacing="0" cellpadding="0">
                    <tr>
                        <td><input type="checkbox" id="chkDontShow" /></td>
                        <td>
                            <span class="iphone_copy_chk">
                                <label for="chkDontShow">&nbsp;Don&rsquo;t show this screen again.</label>
                            </span>
                        </td>
                    </tr>
                </table>

            </div>
        </td>
        <td class="iphone_table_leftRight">&nbsp;</td>
    </tr>
</table>

</div>

</body>
</html>
2
nate_weldon

いくつかの答えをコンパイルした後、次のコードを思い付きました。驚いたのは、タイマーがPC(Chrome、FF)またはAndroid Chromeでフリーズするnotトリガーはバックグラウンドで機能し、可視性チェックのみが信頼できる情報でした。

var timestamp             = new Date().getTime();
var timerDelay              = 5000;
var processingBuffer  = 2000;

var redirect = function(url) {
  //window.location = url;
  log('ts: ' + timestamp + '; redirecting to: ' + url);
}
var isPageHidden = function() {
    var browserSpecificProps = {hidden:1, mozHidden:1, msHidden:1, webkitHidden:1};
    for (var p in browserSpecificProps) {
        if(typeof document[p] !== "undefined"){
        return document[p];
      }
    }
    return false; // actually inconclusive, assuming not
}
var elapsedMoreTimeThanTimerSet = function(){
    var elapsed = new Date().getTime() - timestamp;
  log('elapsed: ' + elapsed);
  return timerDelay + processingBuffer < elapsed;
}
var redirectToFallbackIfBrowserStillActive = function() {
  var elapsedMore = elapsedMoreTimeThanTimerSet();
  log('hidden:' + isPageHidden() +'; time: '+ elapsedMore);
  if (isPageHidden() || elapsedMore) {
    log('not redirecting');
  }else{
    redirect('appStoreUrl');
  }
}
var log = function(msg){
    document.getElementById('log').innerHTML += msg + "<br>";
}

setTimeout(redirectToFallbackIfBrowserStillActive, timerDelay);
redirect('nativeApp://');

JSフィドル

1
ptrk