Как проверить, установлено ли приложение с веб-страницы на iPhone?

Я хочу создать веб-страницу, страницу, которая будет перенаправлять iPhone в магазин приложений, если на iPhone не установлено приложение, но если на iPhone установлено приложение, я хочу, чтобы оно открывало приложение.

Я уже реализовал пользовательский URL-адрес в приложении iPhone, поэтому у меня есть URL-адрес для приложения, который выглядит примерно так:

myapp://

И если этот URL-адрес недействителен, я хочу перенаправить страницу в магазин приложений. Это вообще возможно?

Если я не установил приложение на телефон и не написал myapp:// url в safari, все, что я получил, - это сообщение об ошибке.

Даже если бы существовал отвратительный хак с JavaScript, который я действительно хотел бы знать?

12 ответов

Решение

Насколько я знаю, вы не можете из браузера проверить, установлено приложение или нет.

Но вы можете попробовать перенаправить телефон в приложение и, если ничего не произойдет, перенаправить телефон на указанную страницу, например так:

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

Если вторая строка кода дает результат, то первая строка никогда не выполняется.

Надеюсь это поможет!

Подобный вопрос:

Чтобы продвинуть принятый ответ, вам иногда нужно добавить дополнительный код, чтобы обработать людей, возвращающих браузер после запуска приложения, - функция 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://";

Таким образом, если при выполнении кода произошла остановка (т. Е. Переключение приложения), он не запустится.

iOS Safari имеет функцию, которая позволяет вам добавить "умный" баннер на вашу веб-страницу, который будет ссылаться либо на ваше приложение, если оно установлено, либо на App Store.

Вы делаете это, добавляя meta тег на страницу. Вы даже можете указать подробный URL-адрес приложения, если хотите, чтобы приложение при загрузке делало что-то особенное.

Подробности на странице продвижения приложений Apple с помощью баннеров Smart App.

Механизм обладает преимуществами простоты и представления стандартного баннера. Недостатком является то, что у вас нет большого контроля над внешним видом или местоположением. Кроме того, все ставки отключены, если страница просматривается в браузере, отличном от Safari.

По состоянию на 2017 год, кажется, нет надежного способа определить, установлено ли приложение, и уловка перенаправления не будет работать везде.

Для таких как я, которым нужна глубокая ссылка непосредственно из электронных писем (довольно часто), стоит отметить следующее:

  • Отправка писем с помощью appScheme:// не будет работать нормально, потому что ссылки будут отфильтрованы в Gmail

  • Автоматическое перенаправление на appScheme:// заблокировано Chrome: я подозреваю, что Chrome требует, чтобы перенаправление было синхронным с пользовательским взаимодействием (например, щелчком)

  • Теперь вы можете использовать глубокую ссылку без appScheme:// и это лучше, но для этого требуется современная платформа и дополнительная настройка. Android iOS


Стоит отметить, что другие люди уже задумывались об этом подробно. Если вы посмотрите, как Slack реализует свою функцию "волшебной ссылки", вы можете заметить, что:

  • Он отправляет письмо с обычной http-ссылкой (хорошо с Gmail)
  • На веб-странице есть большая кнопка, которая ссылается на appScheme:// (нормально с Chrome)

@Alistair указал в этом ответе, что иногда пользователи возвращаются в браузер после открытия приложения. Комментатор к этому ответу указал, что используемые значения времени должны были быть изменены в зависимости от версии iOS. Когда нашей команде пришлось иметь дело с этим, мы обнаружили, что значения времени для первоначального тайм-аута и сообщения о том, вернулись ли мы в браузер, должны были быть настроены, и часто они не работали для всех пользователей и устройств.

Вместо того, чтобы использовать произвольный порог разницы во времени для определения того, вернулись ли мы в браузер, имело смысл обнаруживать события "pagehide" и "pagehow".

Я разработал следующую веб-страницу, чтобы помочь диагностировать происходящее. Он добавляет диагностику HTML по мере развертывания событий, главным образом потому, что при использовании таких методов, как ведение журнала консоли, оповещения или Web Inspector, jsfiddle.net и т. Д., Все они имели свои недостатки в этом рабочем процессе. Вместо использования временного порога, Javascript подсчитывает количество событий "pagehide" и "pageshow", чтобы увидеть, произошли ли они. И я обнаружил, что наиболее надежной стратегией было использование начального тайм-аута 1000 (а не 25, 50 или 100, о которых сообщили / предложили другие).

Это может быть подано на локальном сервере, например python -m SimpleHTTPServer и просмотрели на iOS Safari.

Чтобы поиграть с ним, нажмите на ссылку "Открыть установленное приложение" или "Приложение не установлено". Эти ссылки должны открывать соответственно приложение "Карты" или "Магазин приложений". Затем вы можете вернуться в Safari, чтобы увидеть последовательность и время событий.

(Примечание: это будет работать только для Safari. Для других браузеров (например, Chrome) вам нужно будет установить обработчики для событий pagehide/show-эквивалента).

Обновление: Как @Mikko указал в комментариях, события pagehow/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>

Вы можете проверить этот плагин, который пытается решить проблему. Он основан на том же подходе, который описан Миссемисой, Аластером и т. Д., Но вместо этого использует скрытый iframe.

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

Мне нужно сделать что-то вроде этого, и я решил использовать следующее решение.

У меня есть определенный URL веб-сайта, который откроет страницу с двумя кнопками

1) Кнопка One перейти на сайт

2) Кнопка Two, чтобы перейти к приложению (iphone / android phone / tablet), вы можете вернуться к расположению по умолчанию отсюда, если приложение не установлено (например, другой URL или магазин приложений)

3) cookie, чтобы запомнить выбор пользователя

<head>
<title>Mobile Router Example </title>


<script type="text/javascript">
    function set_cookie(name,value)
    {
       // js code to write cookie
    }
    function read_cookie(name) {
       // jsCode to read cookie
    }

    function goToApp(appLocation) {
        setTimeout(function() {
            window.location = appLocation;
              //this is a fallback if the app is not installed. Could direct to an app store or a website telling user how to get 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 BTN -->
                <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>

Следующий ответ все еще работает, протестирован на iOS 10–14. Он основан на предыдущих ответах. я добавил чтобы избавиться от пустого окна вкладки, которое оставалось в браузерах после перенаправления или возврата страницы. Если исправить 2 из 4 сценариев, в которых останется пустая вкладка ... может быть, кто-то другой сможет исправить 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>

После составления нескольких ответов, я пришел к следующему коду. Что меня удивило, так это то, что таймер не зависает на ПК (Chrome, FF) или 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 Fiddle

Я пытался добиться того же в расширении Safari для iOS15. Кажется, что все предыдущие стратегии терпят неудачу - диалог «Открыть в» и диалог «Неверный адрес» полностью равны, оба неблокирующие, поэтому решения на основе таймера предлагают противоречивые результаты, в зависимости от времени, необходимого для загрузки страницы. .

Мое обходное решение состояло в том, чтобы создать модальное всплывающее окно, которое имитирует внешний вид системного приглашения, скрыть его за системным приглашением и закрыть его с помощью прослушивателя событий, когда вкладка теряет фокус. С UX остаются две проблемы:

  1. Невозможно подавить запрос «Неверный адрес». Все, что мы можем сделать (если мы не пойдем по пути универсальных ссылок), - это потом объяснить это с помощью нашей собственной подсказки.
  2. Если пользователь выбирает «Отмена» в приглашении «Открыть в», он или она по-прежнему получает наше приглашение перенаправления.

В следующем коде используются как приведенные выше ответы, так и этот код SO для создания модального всплывающего окна.

Решение по дате намного лучше, чем другие, мне пришлось увеличить время на 50, вот как это пример Tweeter:

//on click or 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;

единственная проблема в Mobile IOS Safari - это когда у вас не установлено приложение на устройстве, и поэтому Safari показывает предупреждение о том, что автоотключение при открытии нового URL-адреса в любом случае является хорошим решением на данный момент!

Не прочитал все это, но, возможно, использовал iframe и добавил источник в "мое приложение:// что угодно".

Затем регулярно проверяйте на заданном интервале страницы 404 или нет.

Вы также можете использовать вызов Ajax. Если ответ 404, то приложение не установлено.

Другие вопросы по тегам