Как проверить, установлено ли приложение с веб-страницы на 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.
Мне нужно сделать что-то вроде этого, и я решил использовать следующее решение.
У меня есть определенный 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"> </td>
<td>
<!-- INTRO -->
<span class="iphone_copy_intro">Check out our new app or go to website</span>
</td>
<td class="iphone_table_leftRight"> </td>
</tr>
<tr>
<td class="iphone_table_leftRight"> </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"> </td>
<td class="iphone_btn_on_mid">
<span class="iphone_copy_btn">
Get The Mobile Applications
</span>
</td>
<td class="iphone_btn_on_right"> </td>
</tr>
</table>
</div>
</td>
<td class="iphone_table_leftRight"> </td>
</tr>
<tr>
<td class="iphone_table_leftRight"> </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"> </td>
<td class="iphone_btn_mid">
<span class="iphone_copy_btn">
Visit Website.com
</span>
</td>
<td class="iphone_btn_right"> </td>
</tr>
</table>
</div>
</td>
<td class="iphone_table_leftRight"> </td>
</tr>
<tr>
<td class="iphone_table_leftRight"> </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"> Don’t show this screen again.</label>
</span>
</td>
</tr>
</table>
</div>
</td>
<td class="iphone_table_leftRight"> </td>
</tr>
</table>
</div>
</body>
</html>
Следующий ответ все еще работает, протестирован на iOS 10–14. Он основан на предыдущих ответах. я добавил
<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://');
Я пытался добиться того же в расширении Safari для iOS15. Кажется, что все предыдущие стратегии терпят неудачу - диалог «Открыть в» и диалог «Неверный адрес» полностью равны, оба неблокирующие, поэтому решения на основе таймера предлагают противоречивые результаты, в зависимости от времени, необходимого для загрузки страницы. .
Мое обходное решение состояло в том, чтобы создать модальное всплывающее окно, которое имитирует внешний вид системного приглашения, скрыть его за системным приглашением и закрыть его с помощью прослушивателя событий, когда вкладка теряет фокус. С UX остаются две проблемы:
- Невозможно подавить запрос «Неверный адрес». Все, что мы можем сделать (если мы не пойдем по пути универсальных ссылок), - это потом объяснить это с помощью нашей собственной подсказки.
- Если пользователь выбирает «Отмена» в приглашении «Открыть в», он или она по-прежнему получает наше приглашение перенаправления.
В следующем коде используются как приведенные выше ответы, так и этот код 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, то приложение не установлено.