如果不处理Android自定义URL方案,如何回归市场?

时间:2011-08-29 13:54:54

标签: android ios url-scheme

我们有一个应用程序来处理自定义URL方案(vstream://)。当有人访问具有某些vstream://内容的网页时,如果他们没有安装我们的应用,我们需要将它们重定向到商店。

在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。 (我在这里找到了这种技术:Is it possible to register a http+domain-based URL Scheme for iPhone apps, like YouTube and Maps?。)

不幸的是,这个技巧在Android中无效。我们检测设备服务器端并编写了这个而不是itms:line:

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

麻烦的是,当你去一个未处理的网址方案时,iOS会抛出一个错误,Android会转到生成的页面。因此,超时永远不会有机会运行。

网页上是否有某种方法可以明确地测试自定义网址方案是否得到处理,或者有人建议像Android这样的黑客可以在Android中运行吗? (当然,我想我需要一个黑客,无论他们使用什么浏览器都可以工作,这可能是一个很高的订单...)

更新: 以下方法在Nexus 7上的Jelly Bean中不起作用。新的Chrome浏览器不会转到生成的页面(因此不需要iFrame),但似乎没有任何方法可以知道URL方案是否是处理。如果是的话,无论如何都会触发超时。如果没有处理,超时会触发。如果我使用onload处理程序和iframe,onload处理程序永远不会触发(无论是否安装了应用程序)。如果我弄清楚如何知道该计划是否得到处理,我会更新...

我在之前的解决方案中删除了“已解决”,因为它不再起作用了。

更新2: 我现在有一个很好的跨平台解决方案,适用于iOS,Android 4.1,Chrome和Android预Chrome。见下文......

更新3: 谷歌打算再打破一切。看看非常好的解决方案,我已经接受了amit_saxena那里的某个地方/

7 个答案:

答案 0 :(得分:18)

更新:谷歌打破了这个。请改为查看新接受的答案。

事实证明,密钥是document.webkitHidden属性。将window.location设置为自定义URL方案并打开时,浏览器将继续运行,但该属性将变为false。因此,您可以对其进行测试,以确定是否已处理自定义URL方案。

以下是一个示例,您可以view live

<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>

答案 1 :(得分: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

答案 2 :(得分: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>

如果安装了应用程序,那么您的网址将启动我,或者它会在指定的包装上启动市场

答案 3 :(得分: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);
}

答案 4 :(得分: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>');

请注意,我将超时时间增加到1000,因为Android实际上在每种情况下都执行了两个操作(不理想,但不是很糟糕),并且需要这个更大的超时来确保Market不会成为用户看到我已经安装好了。

(是的,当然使用document.write是上个世纪的,但我这样老了:)

答案 5 :(得分:2)

由于某些原因,最终的解决方案对我来说不适用于android(它只是我吗?!!)。关键是在安装应用程序时不执行iframe.onload功能,并且在未安装应用程序时执行。

实际上解决方案变得更简单了。以下是“较旧的Android浏览器”部分:

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

    }

答案 6 :(得分:1)

在您的应用中将http服务器作为服务嵌入,侦听本地端口(高于1024,例如:8080),从浏览器发送请求到127.0.0.1:8080。如果您的应用已安装(并且服务正在运行),请启动它,如果请求失败,请转到google play。