【问题标题】:iPhone browser: Checking if iPhone app is installed from browseriPhone 浏览器:检查是否从浏览器安装了 iPhone 应用程序
【发布时间】:2011-11-26 06:39:54
【问题描述】:

我有一个网页,我有一个按钮,可以打开应用程序(如果已安装)或如果未安装应用程序则指向应用商店。 如果安装了 App(我调用“MYAPP://”),这一切都可以工作。但是,如果未安装应用程序,Safari 会显示错误消息“无法打开 URL”,仅此而已。有没有办法从 JScript 中禁用该消息,或者是否有另一种方法可以从 JScript 中找出是否安装了应用程序(而不是点击应用程序 URL)?

致版主:我看到有人问similar question,版主错误地将其标记为重复。请理解这个问题是专门关于从浏览器中进行的。

找到了一些合适的解决方案here

顺便说一句,如果有人对如何为 Android 做同样的事情感兴趣,这里是代码。我们正在使用 Dojo 库:

  dojo.io.iframe.send({
    url: "yourApp://foo/bar",
    load: function(resp) {
      // nothing to do since it will automagically open App
    },
    error: function () {
      window.location = "go to Android market";
    }
  });

【问题讨论】:

    标签: iphone browser


    【解决方案1】:

    Branch,我们使用下面的代码形式——请注意,iframe 适用于更多浏览器。只需替换您应用的 URI 和您的 App Store 链接即可。顺便说一句,如果他们没有安装应用程序,使用 iframe 会消除错误。太棒了!

    <!DOCTYPE html>
    <html>
        <body>
            <script type="text/javascript">
                window.onload = function() {
                    // Deep link to your app goes here
                    document.getElementById("l").src = "my_app://";
    
                    setTimeout(function() {
                        // Link to the App Store should go here -- only fires if deep link fails                
                        window.location = "https://itunes.apple.com/us/app/my.app/id123456789?ls=1&mt=8";
                    }, 500);
                };
            </script>
            <iframe id="l" width="1" height="1" style="visibility:hidden"></iframe>
        </body>
    </html>
    

    如果其他人有更好的解决方案来检测URI方案调用是否真的失败,请发布!我一个都没见过,我花了很多时间寻找。所有现有解决方案仅依赖于用户仍在页面上并触发 setTimeout。

    【讨论】:

    • 谢谢,这是我见过的最好的解决方案。与所有其他的一样,如果没有安装目标应用程序,iOS 8 在打开网页之前会给出“无效地址”消息。这个只是选择任何一个选项,然后执行。现在,让它在 Android 上运行..!
    • 祝你好运。每个浏览器都是不同的。 chrome 意图 vs 标准浏览器 vs facebook webview vs twitter webview vs pinterest。这就是我每天在 Branch 所做的事情
    • 是的,这是一个真正的雷区,我正在发现!如果我有任何重大突破,我会在这里发布......
    • 请注意,我们发现现在这也不适用于 iOS 9。您不能使用 iframe,因此不能抑制错误消息。但是,您可以使用新的通用链接..
    • 它似乎在某些情况下仍然有效,就像你从信使打开链接一样。我的猜测是 UIWebView 和 Safari 是有区别的,但我可能错了
    【解决方案2】:

    这是一个适用于 iO 的代码,即使“无法打开 URL”仍然显示。

        window.location = "yourApp://foo/bar";      
        clickedAt = +new Date;
        setTimeout(function() {
            if (+new Date - clickedAt < 2000) {
                window.location = "go to Android market";
            }
        }, 500);
    

    感谢安卓解决方案。

    【讨论】:

    【解决方案3】:

    在使用 chazbot 的 try/catch 方法之前,我结合了一些东西并使用以下代码检查它是否是 iOS 设备。不幸的是,设备仍然向用户抛出一个弹出框,说地址无效......有人知道这是否是尝试在“try”块中打开无效 URL 的预期行为?

        var i = 0,
        iOS = false,
        iDevice = ['iPad', 'iPhone', 'iPod'];
    
        for ( ; i < iDevice.length ; i++ ) {
            if( navigator.platform === iDevice[i] ){ iOS = true; break; }
        }
    
        try {
            //run code that normally breaks the script or throws error
            if (iOS) { window.location = "myApp://open";}
        }
        catch(e) {
            //do nothing
        }
    

    【讨论】:

      【解决方案4】:

      您可以采取一些措施来改进其他答案。从 iOS 9 开始,可以在UIWebViewSFSafariViewController 中打开链接。您可能希望以不同的方式处理它们。

      SFSafariViewController 在应用程序之间共享 cookie,并与内置的 Safari 共享。因此,在您的应用程序中,您可以通过 SFSafariViewController 发出请求,该请求将设置一个显示“我的应用程序已安装”的 cookie。例如,您打开您的网站,要求您的服务器设置此类 cookie。然后,每当您收到来自 SFSafariViewController 的请求时,您都可以检查该 cookie 并重定向到 MYAPP://(如果找到),或者重定向到应用商店(如果没有)。无需打开网页并执行 javascript 重定向,您可以从您的服务器执行 301。 MessagesSafari 等应用共享这些 cookie。

      UIWebView 非常棘手,因为它完全被沙盒化并且不与其他任何东西共享任何 cookie。所以你必须回退到其他答案中描述的内容:

      window.onload = function() {
        var iframe = document.createElement("iframe");
        var uri = 'MYAPP://';
        var interval = setInterval(function() {
            // Link to the App Store should go here -- only fires if deep link fails                
            window.location = "https://itunes.apple.com/us/app/my.app/id123456789?ls=1&mt=8";
        }, 500);
        iframe.onload = function() {
            clearInterval(interval);
            iframe.parentNode.removeChild(iframe);
            window.location.href = uri;
        };
        iframe.src = uri;
        iframe.setAttribute("style", "display:none;");
        document.body.appendChild(iframe);  
      };
      

      我发现这很烦人,即使您的应用尚未安装,这也会提示用户是否要离开当前应用(转至您的应用)。 (从经验上看,这似乎只在 UIWebView 中是正确的,如果你在普通的 Safari 中这样做,例如不会发生),但这就是我们所得到的!

      您可以将UIWebViewSFSafariViewController 与您的服务器区分开来,因为它们具有不同的用户代理标头:SFSafariViewController 包含 SafariUIWebView 不包含。例如:

      Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E269
      -> UIWebView
      
      Mozilla/5.0 (iPhone; CPU iPhone OS 10_3 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E269 Safari/602.1
      -> SFSafariViewController
      

      其他注意事项:

      • 在第一种方法中,您可能希望处理卸载:如果用户卸载您的应用程序,您仍然有一个 cookie 表明该应用程序存在但它不存在,因此您最终可能会收到 "Can not open URL" 消息。我已经通过在几次尝试都没有打开应用程序后删除 cookie 来处理它(我知道,因为在每次打开应用程序时我都会重置这个失败的尝试 cookie)
      • 在第二种情况下,不清楚使用setInterval 还是setTimeout 更好。超时的问题是,如果它在提示打开时触发,它将被忽略。例如,如果您从 Messenger 打开链接,当 iframe 尝试加载您的应用程序时,操作系统会询问您“离开 Messenger?您即将打开另一个应用程序”。如果您在超时的 500 毫秒内均未响应,则超时中的重定向将被忽略。
      • 最后,即使UIWebView 被沙盒化,您也可以给它一个cookie 来识别它,将它传递到您的深层链接中,并在您的应用程序打开时将此ID 保存为与您的应用程序在您的服务器中的设备相对应。下次,如果您在来自UIWebView 的请求中看到这样的 cookie,您可以检查它是否与应用程序的已知设备匹配,并像以前一样直接使用 301 重定向。

      【讨论】:

        【解决方案5】:

        我认为您仍然可以使用应用程序 url 作为测试。尝试将其包装在 try...catch 块中,

        try {
          //run code that normally breaks the script or throws error
        }
        catch(e) {
          //do nothing
        }
        

        【讨论】:

          猜你喜欢
          • 2019-01-04
          • 2010-09-22
          • 2016-03-06
          • 2011-02-12
          • 2011-04-19
          • 2018-12-28
          • 1970-01-01
          • 2011-07-17
          相关资源
          最近更新 更多