iPhone浏览器:检查iPhone应用程序是否从浏览器安装

发布于 2024-12-06 12:58:50 字数 884 浏览 2 评论 0原文

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

致版主:我看到有人问类似的问题< /a> 且版主错误地将其标记为重复。请理解该问题专门针对从浏览器执行此操作。

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

顺便说一句,如果有人对如何在 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";
    }
  });

I have web page where I have Button that either opens app (if it installed) or directs to App store if app isn't installed.
It all works if App is installed (I call into "MYAPP://"). However, if app is not installed Safari shows error message "Can not open URL" and that's it. Is there way to disable that message from JScript or is there another way to find out from JScript if app installed (instead of hitting app URL)?

To MODERATOR: I saw someone asked similar question and Moderator wrongly marked it as duplicate. Please understand that question was specifically about doing it from Browser.

Found somewhat suitable solution here

BTW if someone interested in how to do same thing for Android, here is code. We are using Dojo library:

  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";
    }
  });

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

·深蓝 2024-12-13 12:58:50

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 触发。

At Branch we use a form of the code below--note that the iframe works on more browsers. Simply substitute in your app's URI and your App Store link. By the way, using the iframe silences the error if they don't have the app installed. It's great!

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

If others have better solutions to detect whether the URI scheme call actually failed, please post! I haven't seen one, and I've spent a ton of time looking. All existing solutions just rely on the user still being on the page and the setTimeout firing.

默嘫て 2024-12-13 12:58:50

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

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

感谢您提供安卓解决方案。

here is a code that works on iOs, even if the "Can not open URL" still show.

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

Thanks for the android solution.

枯叶蝶 2024-12-13 12:58:50

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

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

I think you can still use the app url as a test. Try wrapping it in a try...catch block,

try {
  //run code that normally breaks the script or throws error
}
catch(e) {
  //do nothing
}
初雪 2024-12-13 12:58:50

在使用 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
    }

I've combined a few things and used the following code to check if it's an iOS device before using the try/catch method from chazbot. Unfortunately, the device still throws a pop-up box to the user saying the address is invalid...anyone know if this is expected behavior for trying to open an invalid URL within a "try" block?

    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
    }
情绪失控 2024-12-13 12:58:50

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

SFSafariViewController 跨应用程序以及内置 Safari 共享 cookie。因此,在您的应用中,您可以通过 SFSafariViewController 发出请求,该请求将设置一个 cookie,显示“我的应用已安装”。例如,您打开网站,要求服务器设置此类 cookie。然后,每当您收到来自 SFSafariViewController 的请求时,您都可以检查该 cookie,如果找到它,则重定向到 MYAPP://;如果没有,则重定向到应用商店。 t。无需打开网页并执行 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 表明该应用程序存在,但实际上不存在,因此您最终可能会得到 “无法打开 URL” 消息。我已经通过几次尝试后删除 cookie 来处理它,但最终没有打开应用程序(我知道,因为每次打开应用程序时,我都会重置此失败的尝试 cookie)
  • 在第二种情况下,不清楚您是否'最好使用 setIntervalsetTimeout。超时的问题是,如果它在提示打开时触发,它将被忽略。例如,如果您从 Messenger 打开链接,当 iframe 尝试加载您的应用程序时,操作系统会询问您“离开 Messenger?您将要打开另一个应用程序”。如果您在超时的 500 毫秒内没有响应任何一种方式,则超时内的重定向将被忽略。
  • 最后,即使 UIWebView 已沙箱化,您也可以为其提供一个 cookie 来识别它,将其传递到深层链接中,并在应用程序打开时将此 id 保存为与您的应用程序在服务器中的设备相对应。下次,如果您在来自 UIWebView 的请求中看到这样的 cookie,您可以检查它是否与应用程序匹配已知设备,并像以前一样直接使用 301 进行重定向。

There are a few things you can do to improve on other answers. Since iOS 9, a link can be opened in a UIWebView or in a SFSafariViewController. You might want to handle them differently.

The SFSafariViewController shares cookies across apps, and with the built in Safari. So in your app you can make a request through a SFSafariViewController that will set a cookie that says "my app was installed". For instance you open your website asking your server to set such cookie. Then anytime you get a request from a SFSafariViewController you can check for that cookie and redirect to MYAPP:// if you find it, or to the app store if you don't. No need to open a webpage and do a javascript redirection, you can do a 301 from your server. Apps like Messages or Safari share those cookies.

The UIWebView is very tricky since it is totally sandboxed and shared no cookies with anything else. So you'll have to fallback to what has been described in other answers:

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);  
};

I've found it annoying that this will prompt the user if they want to leave the current app (to go to your app) even when your app is not installed. (empirically that seems only true from a UIWebView, if you do that from the normal Safari for instance that wont happen) but that's all we got!

You can differentiate the UIWebView from the SFSafariViewController from your server since they have different user agent header: the SFSafariViewController contains Safari while the UIWebView doesn't. For instance:

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

Other considerations:

  • in the first approach, you might want to handle uninstalls: if the user uninstalls your app, you still have a cookie that says that the app is there but it's not, so you might end up with the "Can not open URL" message. I've handled it by removing the cookie after a few tries that didn't end up opening the app (which I know because at every app open I'm resetting this failed tries cookie)
  • In the second case, it's unclear if you're better off using a setInterval or setTimeout. The issue with the timeout is that if it triggers while a prompt is on, it will be ignored. For instance if you open the link from Messenger, the os will ask you "Leave Messenger? You're about to open another app" when the iframe tries to load your app. If you don't respond either way within the 500ms of the timeout, the redirection in the timeout will be ignored.
  • Finally even though the UIWebView is sandboxed, you can give it a cookie to identify it, pass it in your deeplink, and save this id as corresponding to device with your app in your server when your app opens. Next time, if you see such a cookie in the request coming from the UIWebView, you can check if it matches a known device with the app and redirect directly with a 301 as before.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文