172

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

iPhoneアプリケーションにカスタムURLをすでに実装しているので、次のようなアプリケーションのURLがあります。

myapp://

また、このURLが無効な場合は、ページをAppStoreにリダイレクトします。これは可能ですか?

電話にアプリケーションをインストールしておらず、Safariでmyapp:// URLを書き込んだ場合、表示されるのはエラーメッセージだけです。

JavaScriptで醜いハックがあったとしても、本当に知りたいです。

4

12 に答える 12

232

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

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

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

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

同様の質問:

于 2012-11-02T14:17:36.460 に答える
173

受け入れられた答えをさらに進めるために、アプリの起動後にブラウザーに戻るユーザーを処理するためのコードを追加する必要がある場合があります。これにより、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://";

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

于 2013-05-23T17:16:39.640 に答える
28

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

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

詳細は、Appleの「スマートアプリバナーを使用したアプリの宣伝」ページにあります。

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

于 2014-08-18T16:17:04.067 に答える
23

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

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

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

  • appScheme://への自動的なリダイレクトはChromeによってブロックされています:Chromeでは、ユーザーの操作(クリックなど)と同期するようにリダイレクトする必要があると思われます

  • appScheme://なしでディープリンクできるようになりました。より優れていますが、最新のプラットフォームと追加のセットアップが必要です。Android iOS


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

  • 通常のHTTPリンクを含むメールを送信します(Gmailでも問題ありません)
  • Webページには、appScheme://にリンクする大きなボタンがあります(ChromeでOK)
于 2017-06-21T08:43:48.663 に答える
11

@Alistairはこの回答で、ユーザーがアプリを開いた後にブラウザーに戻ることがあると指摘しました。その回答へのコメントは、iOSのバージョンに応じて使用される時間の値を変更する必要があることを示しました。

私たちのチームがこれに対処しなければならなかったとき、最初のタイムアウトの時間値と、ブラウザーに戻ったかどうかを確認する必要があり、すべてのユーザーとデバイスで機能しないことがよくありました。

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

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

これは、ローカルサーバーで提供できます。たとえばpython -m SimpleHTTPServer、iOSSafariで表示できます。

それで遊ぶには、「インストールされたアプリを開く」または「アプリがインストールされていません」リンクのいずれかを押します。これらのリンクにより、それぞれマップアプリまたはAppStoreが開きます。その後、Safariに戻って、イベントのシーケンスとタイミングを確認できます。

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

更新: @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>
于 2014-07-30T22:11:37.343 に答える
9

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

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

于 2014-11-19T03:06:52.677 に答える
2

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

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

  1. ボタン1はウェブサイトに移動します

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

  3. ユーザーの選択を記憶するためのCookie

     <head>
         <title>Mobile Router Example </title>
    
    
         <script type="text/javascript">
             function set_cookie(name,value)
             {
                // JavaScript code to write a cookie
             }
             function read_cookie(name) {
                // JavaScript code to read a cookie
             }
    
             function goToApp(appLocation) {
                 setTimeout(function() {
                     window.location = appLocation;
                         // This is a fallback if the app is not installed.
                         // It could direct to an app store or a website
                         // telling user how to get the 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 button -->
                         <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>
    
于 2013-09-17T19:50:08.287 に答える
2

いくつかの答えをまとめた後、私は次のコードを思いついた。私が驚いたのは、タイマーがPC(ChromeとFirefox)またはAndroid Chromeでフリーズしないことでした。トリガーはバックグラウンドで機能し、可視性チェックが唯一の信頼できる情報でした。

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フィドル

于 2016-11-30T12:32:28.463 に答える
1

次の回答は引き続き機能し、iOS 10から14でテストされています。これは、以前の回答に基づいています。window.close()リダイレクトまたはページが戻った後にブラウザに残された空のタブウィンドウを取り除くために追加しました。空白のタブが残される4つのシナリオのうち2つを修正した場合、他の誰かが3番目と4番目を修正できる可能性があります

<script>
var now = new Date().valueOf();
setTimeout(function () {
  // time stamp comaprison prevents redirecting to app store a 2nd time
  if (new Date().valueOf() - now > 100) {
    window.close() ;  // scenario #4
    // old way - "return" - but this would just leave a blank page in users browser
    //return;  
  }
  if (isIOS == 1) {
    // still can't avoid the "invalid address" safari pops up
    // but at least we can explain it to users
    var msg = "'invalid address' = MyApp NOT DETECTED.\n\nREDIRECTING TO APP STORE" ;
  } else {
    var msg = "MyApp NOT DETECTED\n\nREDIRECTING TO APP STORE" ;
  }
  if (window.confirm(msg)) {
    window.location = "<?=$storeUrl?>";
    // scenario #2 - will leave a blank tab in browser
  } else {
    window.close() ;  // scenario #3
  }
}, 50);
window.location = "<?=$mobileUrl?>";  
// scenario #1 - this will leave a blank tab
</script>
于 2021-08-04T15:10:48.813 に答える
0

私はiOS15用のSafari拡張機能で同じことを達成しようとしています。以前のすべての戦略は失敗したようです-「開く」ダイアログと「無効なアドレス」ダイアログは完全に等しく、両方とも非ブロッキングであるため、タイマーベースのソリューションは、ページの読み込みにかかる時間に応じて、一貫性のない結果を提供します。

私の回避策は、モーダルポップアップ内にアプリストアリダイレクトメッセージを作成し、システムプロンプトの外観を模倣し、システムプロンプトの背後に隠し、タブがフォーカスを失ったときにイベントリスナーでメッセージを閉じることでした。UXには2つの問題が残っています。

  1. 「無効なアドレス」プロンプトを抑制する方法はありません。私たちにできることは(ユニバーサルリンクパスに行かない場合)、後で独自のプロンプトで説明することだけです。
  2. ユーザーが[開く]プロンプトから[キャンセル]を選択した場合でも、リダイレクトプロンプトが表示されます。

次のコードは、上記の回答とモーダルポップアップを作成するためのこのSOコードの両方の恩恵を受けました。

// Change the following vars to suit your needs
var my_app_name = "My App";
var my_app_id = "id1438151717"
var my_app_scheme = "myapp://do.this"

function toggleModal(isModal, inputs, elems, msg) {
  for (const input of inputs) input.disabled = isModal;
  modal.style.display = isModal ? "block" : "none";
  elems[0].textContent = isModal ? msg : "";
}

function myConfirm(msg) {
  const inputs = [...document.querySelectorAll("input, textarea, select")].filter(input => !input.disabled);
  const modal = document.getElementById("modal");
  const elems = modal.children[0].children;

  return new Promise((resolve) => {
    toggleModal(true, inputs, elems, msg);
    elems[3].onclick = () => resolve(true);
    elems[4].onclick = () => resolve(false);
  }).then(result => {
    toggleModal(false, inputs, elems, msg);
    return result;
  });
}

function redirectMessage() {
  var r = myConfirm("To download " + my_app_name + ", tap OK.");
  return r.then(ok => {
    if (ok) {
      console.log("Redirecting to the App Store...");
      window.location = "itms-apps://itunes.apple.com/app/" + my_app_id;
    } else {
      console.log("User cancelled redirect to the App Store");
    }
    return ok;
  });
}

function prepareListener() {
  document.addEventListener("visibilitychange", function() {
    const inputs = [...document.querySelectorAll("input, textarea, select")].filter(input => !input.disabled);
    const modal = document.getElementById("modal");
    const elems = modal.children[0].children;

    if (!document.hasFocus()) {
      console.log("User left tab. Closing modal popup")
      toggleModal(false, inputs, elems, "");
    }
  });
}

function onTap() {
  setTimeout(function() {
    // We can't avoid the "invalid address" Safari popup,
    // but at least we can explain it to users.
    // We will create a modal popup behind it, which the
    // event listener will close automatically if the app 
    // opens and we leave the tab

    redirectMessage()

  }, 50);
  window.location = my_app_scheme;
}

prepareListener()
#modal {
  display: none;
  position: fixed;
  z-index: 1;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background: rgb(0, 0, 0);
  background: rgba(0, 0, 0, 0.4);
  font-family: "ms sans serif", arial, sans-serif;
  font-size: medium;
  border-radius: 15px;
}

#modal>div {
  position: relative;
  padding: 10px;
  width: 320px;
  height: 60px;
  margin: 0 auto;
  top: 50%;
  margin-top: -45px;
  background: white;
  border: 2px outset;
  border-radius: 15px;
}

#cancel_button {
  position: fixed;
  right: 50%;
  margin-right: -95px;
  bottom: 50%;
  margin-bottom: -32px;
  padding: 0;
  border: none;
  background: none;
  color: rgb(0, 122, 255);
  font-size: medium;
  font-weight: normal;
}

#ok_button {
  position: fixed;
  right: 50%;
  margin-right: -140px;
  bottom: 50%;
  margin-bottom: -32px;
  padding: 0;
  border: none;
  background: none;
  color: rgb(0, 122, 255);
  font-size: medium;
  font-weight: semi-bold;
}
<div id="modal">
  <div>
    <div></div><br><br>
    <button id="ok_button">OK</button>
    <button id="cancel_button">Cancel</button>
  </div>
</div>

<p><a href="#" onclick="onTap();"> Tap here to open app </a></p>

于 2021-10-07T21:42:49.147 に答える
-2

日付ソリューションは、他のソリューションよりもはるかに優れています。私はそのように時間を50に増やす必要がありました。

これはTwitterの例です。

// On click of your event handler...
var twMessage = "Your Message to share";
var now = new Date().valueOf();
setTimeout(function () {
   if (new Date().valueOf() - now > 100) 
       return;
   var twitterUrl = "https://twitter.com/share?text=" + twMessage;
   window.open(twitterUrl, '_blank');
}, 50);
window.location = "twitter://post?message=" + twMessage;

モバイルiOSSafariでの唯一の問題は、デバイスにアプリがインストールされていない場合です。そのため、Safariは、新しいURLが開かれると自動的に閉じるアラートを表示します。とにかく、それは今のところ良い解決策です!

于 2013-05-30T11:06:48.103 に答える
-6

これらの回答をすべて読んだわけではありませんが、iframeを使用して、ソースを「my app://whatever」に追加している可能性があります。

次に、ページの設定間隔が404かどうかを定期的に確認します。

Ajax呼び出しを使用することもできます。404応答がある場合、アプリはインストールされていません。

于 2015-11-29T02:00:31.547 に答える