web-dev-qa-db-ja.com

AndroidカスタムURLスキームが処理されない場合にマーケットプレイスにフォールバックする方法は?

カスタム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割り当てが失敗すると、ダイアログボックスが表示される前にタイムアウトがApp Storeを飛び越えます。 (私はここでこのテクニックを見つけました: YouTubeやマップなどのiPhoneアプリにhttp +ドメインベースのURLスキームを登録することは可能ですか? 。)

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

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

問題は、ハンドルされていないURLスキームに移動するとiOSがエラーをスローするのに対し、Androidは生成されたページに移動するため、タイムアウトが実行される機会を得ることはありません。

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

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

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

更新2:iOS、Android 4.1、およびAndroid pre-Chromeで動作します。以下を参照してください。 。

更新3:Googleは意図をもってすべてを再び壊しました。どこかでamit_saxenaが受け入れた非常に良い解決策を確認してください/

25
Joshua Smith

以下は、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

15
amit_saxena

更新:グーグルはこれを破った。代わりに新しい承認済みの回答をご覧ください。

結局のところ、重要なのは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>
18
Joshua Smith

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

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は私を開始します。

14
Christopher-BZC

@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);
}
6
vmus

解決しました!トリックは、場所を設定するのではなく、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は実際にはすべてのケースで両方のアクションを実行するので(理想的ではないがひどいわけではありません)、Marketが私がすでにインストールされているときにユーザーに表示されるものになります。

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

4
Joshua Smith

いくつかの理由により、Android(これは私だけですか?!!)そして、ISアプリがインストールされていないときに実行されます。

ソリューションは実際には少し単純になります。これは、「Older Android Browser "」部分のセグメントです:

    } 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);

    }
2
Jun Sun

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

1
javamonk