25

カスタムURLスキーム(vstream://)を処理するアプリがあります。誰かがvstream://コンテンツを含むWebページにアクセスした場合、アプリがインストールされていない場合は、ストアにリダイレクトする必要があります。

iOSでは、これを行います。

setTimeout(function() {
  window.location =
    "itms://itunes.apple.com/us/app/kaon-v-stream/id378890806?mt=8&uo=4";
}, 25);

window.location = "vstream:view?code=...stuff...";

割り当てが失敗した場合window.location、ダイアログボックスが表示される前にタイムアウトがAppStoreを飛び越えます。(このテクニックをここで見つけました:YouTubeやマップなどのiPhoneアプリにhttp +ドメインベースのURLスキームを登録することは可能ですか?

残念ながら、このトリックはAndroidでは機能しません。デバイスサーバー側を検出し、itmsの代わりにこれを記述しました:line:

"market://details?id=com.kaon.android.vstream";

問題は、未処理のURLスキームに移動するとiOSがエラーをスローするのに対し、Androidは生成されたページに移動することです。したがって、タイムアウトが実行される機会はありません。

カスタムURLスキームが処理されるかどうかを明示的にテストする方法は、Webページにありますか、または誰かがAndroidで機能するこのようなハックを提案できますか?(もちろん、使用しているブラウザに関係なく機能するハックが必要だと思います。これはおそらく難しい注文です...)

更新:以下のアプローチは、Nexus7のJellyBeanでは機能しません。新しいChromeブラウザは生成されたページに移動しません(したがって、iFrameは必要ありません)が、URLかどうかを知る方法はないようです。スキームが処理されました。もしそうなら、とにかくタイムアウトが発生します。処理されなかった場合、タイムアウトが発生します。onloadハンドラーとiframeを使用すると、onloadハンドラーが起動しません(アプリがインストールされているかどうかに関係なく)。スキームが処理されたかどうかを知る方法がわかったら更新します...

以前のソリューションの「解決済み」は機能しなくなったため、削除しました。

更新2:iOS、Chromeを搭載したAndroid 4.1、およびChromeより前のAndroidで動作する優れたクロスプラットフォームソリューションがあります。下記参照...

更新3:グーグルは意図的にすべてを再び壊した。どこかでamit_saxenaによって受け入れられた非常に素晴らしい解決策をチェックしてください/

4

7 に答える 7

18

更新:グーグルはこれを破った。代わりに、新しく受け入れられた回答を参照してください。

重要なのは、document.webkitHiddenプロパティです。window.locationをカスタムURLスキームに設定して開くと、ブラウザーは実行を続けますが、そのプロパティはfalseになります。したがって、それをテストして、カスタムURLスキームが処理されたかどうかを判断できます。

これがサンプルで、ライブで見ることができます

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Starting App...</title>
<script>

var URL = "kaonkaon://product.html#malvern;6";
var MARKET = "market://details?id=com.kaon.android.lepton.kaon3d";
var ITUNES = "itms://itunes.apple.com/us/app/kaon-interactive-3d-product/id525051513?mt=8&uo=4";
var QR = "http://goo.gl/gz07g"; // this should be a shortened link back to this page

function onLoad() {

    if (navigator.userAgent.match(/Android/)) {

        if (navigator.userAgent.match(/Chrome/)) {

            // Jelly Bean with Chrome browser
            setTimeout(function() {
                if (!document.webkitHidden)
                    window.location = MARKET;
            }, 1000);

            window.location = URL;

        } else {

            // Older Android browser
            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/)) {

         // IOS
         setTimeout(function() {
             if (!document.webkitHidden)
                 window.location = ITUNES;
         }, 25);

         window.location = URL;

     } else {

         // Not mobile
         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>
于 2012-09-24T20:21:32.177 に答える
15

以下は、ほとんどのAndroidブラウザで機能するコードスニペットです。

<script type="text/javascript">
    var custom = "myapp://custom_url";
    var alt = "http://mywebsite.com/alternate/content";
    var g_intent = "intent://scan/#Intent;scheme=zxing;package=com.google.zxing.client.android;end";
    var timer;
    var heartbeat;
    var iframe_timer;

    function clearTimers() {
        clearTimeout(timer);
        clearTimeout(heartbeat);
        clearTimeout(iframe_timer);
    }

    function intervalHeartbeat() {
        if (document.webkitHidden || document.hidden) {
            clearTimers();
        }
    }

    function tryIframeApproach() {
        var iframe = document.createElement("iframe");
        iframe.style.border = "none";
        iframe.style.width = "1px";
        iframe.style.height = "1px";
        iframe.onload = function () {
            document.location = alt;
        };
        iframe.src = custom;
        document.body.appendChild(iframe);
    }

    function tryWebkitApproach() {
        document.location = custom;
        timer = setTimeout(function () {
            document.location = alt;
        }, 2500);
    }

    function useIntent() {
        document.location = g_intent;
    }

    function launch_app_or_alt_url(el) {
        heartbeat = setInterval(intervalHeartbeat, 200);
        if (navigator.userAgent.match(/Chrome/)) {
            useIntent();
        } else if (navigator.userAgent.match(/Firefox/)) {
            tryWebkitApproach();
            iframe_timer = setTimeout(function () {
                tryIframeApproach();
            }, 1500);
        } else {
            tryIframeApproach();
        }
    }

    $(".source_url").click(function (event) {
        launch_app_or_alt_url($(this));
        event.preventDefault();
    });
</script>

source_urlアンカータグにクラスを追加する必要があります。

私はここでそれについてもっとブログを書きました:

http://aawaara.com/post/88310470252/smallest-piece-of-code-thats-going-to-change-the

于 2014-06-09T22:10:24.997 に答える
14

これがあなた方全員を救う答えです!

https://developers.google.com/chrome/mobile/docs/intents

<a href="intent://scan/#Intent;scheme=zxing;package=com.google.zxing.client.android;end"> Take a QR code </a>

アプリがインストールされている場合は、URLが私を開始します。そうでない場合は、指定されたパッケージで市場を開始します。

于 2013-09-25T13:09:12.723 に答える
6

@jesmith、これはAndroidでのダブルアクションを修正するクリーンバージョンです。

if (navigator.appVersion.indexOf('iPhone') > -1) {
  setTimeout(function noapp() { window.location="http://itunes.apple.com/app/id378890806?mt=8"; }, 25);
  window.location = 'vstream:';
}
else if (navigator.userAgent.indexOf('Android') > -1) {
  var iframe = document.createElement('iframe');
  iframe.style.visibility = 'hidden';
  iframe.src = 'vstream:';
  iframe.onload = function noapp() { window.location="market://details?id=com.kaon.android.vstream"; };
  document.body.appendChild(iframe);
}
于 2012-03-21T10:52:53.753 に答える
4

解決しました!秘訣は、場所を設定する代わりに、IFRAMEでアプリを開くことです。

setTimeout(function() {
  window.location =
    "market://details?id=com.kaon.android.vstream";
}, 1000);

document.write('<iframe style="border:none; width:1px; height:1px;" src="vstream:view?code='+code+'"></iframe>');

Androidは実際にはすべての場合に両方のアクションを実行するため(理想的ではありませんが、ひどいわけではありません)、タイムアウトを1000に増やしたことに注意してください。この大きなタイムアウトは、Marketがユーザーに表示されるものにならないようにするために必要です。私はすでにインストールされています。

(もちろん、document.writeの使用は前世紀ですが、私はそのように古い学校です:)

于 2011-08-29T23:19:58.107 に答える
2

いくつかの理由で、Androidでは最終的な解決策が機能しません(それは私だけですか?!!)。重要なのは、iframe.onload関数は、アプリがインストールされているときは実行されず、アプリがインストールされていないときに実行されるということです。

解決策は実際には少し簡単になります。「古いAn​​droidブラウザ」の部分のセグメントは次のとおりです。

    } else {

        // Older Android browser
        var iframe = document.createElement("iframe");
        iframe.style.border = "none";
        iframe.style.width = "1px";
        iframe.style.height = "1px";
        iframe.onload = function () { window.location = MARKET; };
        iframe.src = URL;
        document.body.appendChild(iframe);

    }
于 2012-10-05T22:11:19.940 に答える
1

httpサーバーをサービスとしてアプリに埋め込み、ローカルポート(1024より高い、例:8080)をリッスンし、ブラウザーから127.0.0.1:8080にリクエストを送信します。アプリがインストールされている(そしてサービスが実行されている)場合はアプリを起動し、リクエストが失敗した場合はGooglePlayに移動します。

于 2015-01-06T02:08:50.357 に答える