如何检查iPhone上的网页是否安装了应用程序?

时间:2012-10-24 07:42:42

标签: iphone ios web-applications mobile-safari

我想创建一个网页,如果iPhone没有安装应用程序,该网页会将iPhone重定向到应用程序商店,但如果iPhone安装了应用程序,我希望它能够打开应用程序。

我已经在iPhone应用程序中实现了一个自定义URL,所以我有一个类似于应用程序的URL:

myapp://

如果此网址无效,我希望该网页重定向到应用商店。 这有可能吗?

如果我没有在手机上安装该应用程序并在safari中编写myapp:// url,我得到的只是一条错误消息。

即使存在javascript的丑陋黑客,我真的很想知道吗?

11 个答案:

答案 0 :(得分:173)

据我所知,您无法通过浏览器检查是否安装了应用。

但您可以尝试将手机重定向到应用,如果没有任何反应,请将手机重定向到指定的页面,如下所示:

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

如果第二行代码给出结果,那么第一行永远不会被执行。

希望这有帮助!

类似的问题:

答案 1 :(得分:144)

为了进一步接受已接受的答案,您有时需要添加额外的代码来处理启动应用程序后返回浏览器的人员 - 只要他们这样做,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://";

这样,如果代码执行冻结(即应用程序切换),它就不会运行。

答案 2 :(得分:27)

iOS Safari有一项功能,允许您在网页中添加“智能”横幅,该横幅将链接到您的应用程序(如果已安装)或App Store。

您可以通过向页面添加meta标记来完成此操作。如果您希望应用在加载时执行特殊操作,您甚至可以指定详细的应用URL。

详情请见Apple的Promoting Apps with Smart App Banners页面。

该机制具有易于呈现标准化横幅的优点。缺点是您无法控制外观或位置。此外,如果在Safari以外的浏览器中查看页面,则所有投注均已关闭。

答案 3 :(得分:9)

@Alistair在this answer中指出,有时用户在打开应用后会返回浏览器。该答案的评论者表示,使用的时间值必须根据iOS版本进行更改。当我们的团队不得不处理这个问题时,我们发现初始超时的时间值以及我们是否已经返回浏览器必须进行调整,并且通常不适用于所有用户和设备。

不是使用任意时差阈值来确定我们是否已返回浏览器,而是检测" Pagehide"和" pageshow"事件

我开发了以下网页来帮助诊断发生了什么。它随着事件的展开而增加了HTML诊断功能,主要是因为使用控制台日志记录,警报或Web Inspector,jsfiddle.net等技术都在这个工作流程中存在缺陷。 Javascript不是使用时间阈值,而是计算" Pagehide"的数量。和" pageshow"事件,看他们是否已经发生。我发现最强大的策略是使用1000的初始超时(而不是其他人报告/建议的25,50或100)。

这可以在本地服务器上提供,例如python -m SimpleHTTPServer并在iOS Safari上查看。

要使用它,请按"打开已安装的应用程序"或"未安装应用程序"链接。这些链接应分别导致地图应用程序或App Store打开。然后,您可以返回Safari查看事件的顺序和时间。

(注意:这仅适用于Safari。对于其他浏览器(例如Chrome),您必须为pagehide / show-equivalent事件安装处理程序。)

更新正如@Mikko在评论中指出的那样,iOS8中显然不再支持我们正在使用的pageshow / pagehide事件。

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

答案 4 :(得分:9)

您可以查看试图解决问题的插件。它基于missemisa和Alastair等描述的相同方法,但使用隐藏的iframe代替。

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

答案 5 :(得分:9)

截至2017年,似乎没有可靠的方法来检测安装的应用程序,并且重定向技巧无处不在。

对于像我这样需要直接从电子邮件深层链接的人(很常见),值得注意以下几点:

  • 使用appScheme://发送电子邮件将无效,因为链接将在Gmail中过滤

  • 自动重定向到appScheme://被Chrome阻止:我怀疑Chrome要求重定向与用户互动同步(如点击)

  • 您现在可以在没有appScheme的情况下进行深层链接://并且它更好,但它需要一个现代平台和其他设置。 Android iOS

值得注意的是,其他人已经深入考虑过这一点。如果你看看Slack如何实现他的“魔术链接”功能,你会注意到:

  • 它会发送一封包含常规http链接的电子邮件(可以使用Gmail)
  • 网页上有一个很大的按钮,可以链接到appScheme://(可以使用Chrome)

答案 6 :(得分:2)

我需要做这样的事情,我最终得到了以下解决方案。

我有一个特定的网站网址,可以打开一个带有两个按钮的页面

1)按钮一转到网站

2)按钮2转到应用程序(iphone / android手机/平板电脑)如果未安装应用程序(如其他网址或应用程序商店),您可以从此处回退到默认位置

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>

答案 7 :(得分:1)

编译几个答案后,我想出了以下代码。让我感到惊讶的是,计时器在PC(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

答案 8 :(得分:1)

以下答案仍然有效,在 iOS 10 到 14 上进行了测试。它建立在早期答案的基础上。我添加了 window.close() 以摆脱重定向或页面返回后留在浏览器中的空标签窗口。如果修复了 4 个会留下空白标签的场景中的 2 个......也许其他人可以修复第 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>

答案 9 :(得分:-2)

日期解决方案比其他人好得多,我不得不像这样增加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会在新网址打开时显示自动发出警报,无论如何现在都是一个很好的解决方案!

答案 10 :(得分:-3)

没有阅读所有这些内容,但可能会使用iframe并将源代码添加到“my app:// whatever”。

然后定期检查页面的设置间隔是否为404。

您也可以使用Ajax调用。如果404响应,则表示未安装app。