Как вернуться к рынку, когда пользовательская схема URL Android не обрабатывается? - PullRequest
24 голосов
/ 29 августа 2011

У нас есть приложение, которое обрабатывает пользовательскую схему 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 до появления диалогового окна.(Я нашел эту технику здесь: Можно ли зарегистрировать схему URL на основе домена http + для приложений iPhone, таких как YouTube и Карты? .)

К сожалению, этот прием не работаетв Android.Мы обнаружили серверную часть устройства и записали это вместо строки itms: line:

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

Проблема в том, что iOS выдает ошибку при переходе по необработанной схеме URL, Android переходит на сгенерированную страницу.Следовательно, тайм-аут никогда не запускается.

Есть ли на веб-странице какой-либо способ явно проверить, обрабатывается ли пользовательская схема URL, или кто-то может предложить такой взлом, который будет работать вAndroid?(Конечно, я полагаю, что мне нужен взлом, который будет работать независимо от того, какой браузер они используют, что, вероятно, непросто)Nexus 7. Новый браузер Chrome не переходит на сгенерированную страницу (поэтому iFrame не нужен), но, похоже, нет никакого способа узнать, была ли обработана схема URL.Если это так, тайм-аут срабатывает в любом случае.Если это не было обработано таймаутом пожаров.Если я использую обработчик загрузки и iframe, обработчик загрузки никогда не срабатывает (установлено приложение или нет).Я обновлюсь, если когда-нибудь выясню, как узнать, была ли обработана схема ...

Я удалил "Решено" в моем предыдущем решении, поскольку оно больше не работает.

ОБНОВЛЕНИЕ 2: Теперь у меня есть хорошее кроссплатформенное решение, которое работает на iOS, Android 4.1 с Chrome и Android pre-Chrome.См. Ниже ...

Обновление 3: Google снова все сломал с намерениями.Посмотрите ОЧЕНЬ хорошее решение, которое я принял от amit_saxena где-то там /

Ответы [ 7 ]

18 голосов
/ 25 сентября 2012

ОБНОВЛЕНИЕ: Google сломал это. Вместо этого смотрите новый принятый ответ.

Ключом оказывается свойство document.webkitHidden. Когда вы задаете для window.location собственную схему URL, и она открывается, браузер продолжает работать, но это свойство становится ложным. Таким образом, вы можете проверить его, чтобы определить, была ли обработана пользовательская схема 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>
15 голосов
/ 10 июня 2014

Ниже приведен фрагмент рабочего кода для большинства браузеров 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

14 голосов
/ 25 сентября 2013

Это ответ, который спасет вас всех!

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-адрес запустит меня, если приложение установлено, иначе оно запустит рынок науказанная упаковка

6 голосов
/ 21 марта 2012

@ 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 голосов
/ 30 августа 2011

Решено! Хитрость заключается в том, чтобы открыть мое приложение в 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 фактически выполняет оба действия в каждом случае (не идеальный, но не ужасный), и этот больший тайм-аут необходим для того, чтобы Маркет не оказался тем, что пользователь видит, когда я уже установлен.

(И да, конечно, использование document.write - это прошлый век, но я в таком духе:)

2 голосов
/ 06 октября 2012

По некоторым причинам, у меня на андроиде не работает окончательное решение (это только у меня? !!). Ключ в том, что функция 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);

    }
1 голос
/ 06 января 2015

Вставьте http-сервер в ваше приложение в качестве службы, прослушивайте локальный порт (выше 1024, например: 8080), отправьте запрос из браузера на номер 127.0.0.1:8080. Если ваше приложение установлено (и служба запущена), запустите его, если запрос не выполнен, перейдите в Google Play.

...