检查Javascript中是否支持URL方案

65

有没有办法使用JavaScript检查手机上当前是否已注册URL方案?


3
我发现这里发布的解决方案要好得多:https://dev59.com/oGw05IYBdhLWcg3w41wp - benathon
10个回答

64

不是无缝的。 但是有一种类似于检查弹出窗口是否被阻止的方法。

当您尝试一个不被支持的URL scheme时,Safari会警告用户它不知道如何处理它,并停留在同一页上。

因此,如果您给您的应用程序调用一些时间来激活,比如300毫秒,然后做一些其他事情来响应scheme的不存在。

这不是最美观的方法,但它可以工作:

function startIThrown(){
  document.location = 'ithrown://restart';
  setTimeout(function(){
    if(confirm('You do not seem to have iThrown installed, do you want to go download it now?')){
      document.location = 'http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=293049283&mt=8&uo=6';
    }
  }, 300);
}

<a href="#" onclick="startIThrown()">Restart iThrown</a>

2
值得一试,但确实这是一种不太好的解决方案。即使在返回页面时URL方案通过,该函数仍会被调用。因此,无论如何用户都会收到警报弹窗。取决于他的设备是否支持该方案,可能是1或2。 - samvermette
9
有一个相对复杂的解决方法。如果URL方案可行,那么您的应用程序可以向服务器发送确认消息。然后当您回到应用程序时,让它向服务器发出请求,以查看应用程序是否成功打开。虽然有些复杂,但这是可行的。 - Amir
7
如果应用程序未安装,有没有不显示那个极其不友好的错误的方式? - devios1
iOS 13.3的解决方案,可以与“极其不友好的错误”很好地协作:https://gist.github.com/diachedelic/0d60233dab3dcae3215da8a4dfdcd434 - diachedelic
它能在iOS 15及以上版本上运行吗? - RohitK

39

这里有一个解决方案,当你从应用程序回来时不会显示弹出窗口,它假定你离开时间超过400毫秒:

function startiThrown() {
    document.location = appurl;
    var time = (new Date()).getTime();
    setTimeout(function(){
        var now = (new Date()).getTime();

        if((now - time)<400) {
            if(confirm('You do not seem to have iThrown installed, do you want to go download it now?')){
            document.location = 'http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=293049283&mt=8&uo=6';
            }
         }
    }, 300);
}

我们遇到了一个问题,这个解决方案中的“now”变量完全错误。我们可以在应用程序中等待几分钟,返回浏览器,然后得到确认。似乎休眠唤醒过程存在缺陷。 - JoshNaro

14

我发现pagehide事件比依赖系统时间更加稳定。对于那些喜欢非jQuery方式的人,这里是代码片段。


  var appurl = 'custom://url';
  var appstore = 'https://itunes.apple.com/us/app/your-app';

  var timeout;
  function preventPopup() {
    clearTimeout(timeout);
    timeout = null;
    window.removeEventListener('pagehide', preventPopup);
  }
  function startApp() {
    window.location = appurl;
    timeout = setTimeout(function(){
      if(confirm('You do not seem to have the App installed, do you want to go download it now?')){
        document.location = appstore;
      }
    }, 1000);
    window.addEventListener('pagehide', preventPopup);
  }

那段代码无法运行。当存在模式且它与可执行文件相关联时,浏览器会询问是否要运行该应用程序。这种延迟导致超时到达并且显然会执行 "confirm" 函数。 - jstuardo

9
另一个很好的解决方法(至少在最新浏览器版本中有效)是在短暂的超时后检查浏览器窗口是否具有焦点,这样您就可以仅在URI方案未起作用时向用户显示对话框。
HTML:
<a class="uri-link" data-uri="qobuzapp://" href="#">URI</a>​

Javascript(这里使用jQuery):

var windowHasFocus;

$(window).focus(function() {
  windowHasFocus = true;
}).blur(function() {
  windowHasFocus = false;
});

function goToUri(uri) {
  window.location = uri;
  setTimeout(function(){
    if (windowHasFocus) {
      if (confirm('You do not seem to have Qobuz installed, do you want to go download it now?')){
        window.location = 'http://www.qobuz.com';
      }
    }
  }, 100);
}

$('a').on('click', function(){ 
  goToUri($(this).data('uri')); 
});​

那段代码不起作用。当模式存在并与可执行文件相关联时,浏览器会询问是否要运行该应用程序。这种延迟导致超时到达,显然会执行“确认”函数。 - jstuardo

8

iOS 6.0起,苹果推出了智能应用横幅(Smart App Banners),这是我们大多数人所需要的:

  • 如果应用未安装,则发送到App Store。
  • 使用app-argument参数打开具有特定深度链接的应用程序。

请包含以下元标记:

<meta name="apple-itunes-app" content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL">

taken from here: Safari Web Content Guide


4
不,不是来自网页。

我记得应用程序可以检查这个,但我可能是错的。 - Andrew Grant
2
谢谢您的快速回答。据我所知,从本地代码方面来看,可以通过openUrl:进行检查,但我还没有测试过。 - jackb
12
@Brent Royal-Gordon:不是的。原生的iPhone应用可以通过调用**canOpenURL:**来检查。 - Di Wu
4
可以通过以下网页了解如何为 iPhone 应用程序注册基于 HTTP 域的 URL 方案:https://dev59.com/63NA5IYBdhLWcg3wC5Xh#1109200 - amok
这可能会有所帮助... https://dev59.com/oGw05IYBdhLWcg3w41wp - Underdog
1
这是那种“事实上正确,但实际上并不是很有用”的答案之一。这个答案回答了该提问者在一开始可能应该问的问题! - funkybro

2

这里是前两个解决方案的变体。它将创建一个可以在Google Chrome中打开的链接。如果失败,它将使用http打开链接。

<script>
 function checkChrome(h){
  document.location=h;
  var time = (new Date()).getTime();
  setTimeout(function(){
   var now = (new Date()).getTime();
   if((now-time)<400) {
    if(confirm('Missing Chrome. Download it now?')){
     document.location = 'http://itunes.apple.com/us/app/chrome/id535886823?mt=8';
    } else {
     document.location=h.replace('googlechrome','http');
    }
   }
  }, 300);
 }
</script>

<a href="googlechrome://www.google.com" onclick="checkChrome(this.href);return false;">Open Google with Chrome</a>

1
这是基于mrahman的答案。如JoshNaro所指出,new Date()在timeout内调用时会返回错误的日期。测试表明,在应用程序停用之前启动的线程中,日期不会更新。
在激活后再进行一个丑陋的setTimeout调用将创建一个新的线程,并带有当前日期。
这在iOS 8上进行了测试。
function startiThrown() {
    document.location = appurl;
    var time = (new Date()).getTime();
    setTimeout(function(){
        setTimeout(function(){ // <-- start new thread after activation
            var now = (new Date()).getTime();
            if((now - time)<400) {
                if(confirm('You do not seem to have iThrown installed, do you want to go download it now?')){
                    document.location = 'http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=293049283&mt=8&uo=6';
                }
            }
        }, 10); // <-- start new thread after activation
    }, 300);
}

0

我尝试只使用“pagehide”事件,但在Firefox中无法工作。我创建了这个版本http://jsfiddle.net/thiagomata/6tvoc4f1/2/,可以在Firefox、Google Chrome和Safari中运行。我还没有在Internet Explorer中进行测试。

为了使它在Firefox中工作,有一件必要的事情是使用Iframe来设置src。这使我能够调用应用程序而不离开我的页面。

<a class="uri-link" href="#" 
  data-uri-app="myapp://" 
  data-url-app-not-found="http://www.google.com?q=not-found-link"
  >
  Example 1
</a>​
<a class="uri-link" href="#" 
  data-uri-app="myapp://" 
  data-url-app-not-found="http://www.google.com?q=not-found-link"
  data-url-app-found="http://www.google.com?q=found-link"
  >
  Example 2
</a>​
<a class="uri-link"  href="#"
  data-uri-app="notexists://" 
  data-url-app-not-found="http://www.google.com?q=not-exists"
>
  Example 3
</a>​
<iframe id="callapp" style="display:none"></iframe>

不错的概念。尽管应用程序已经安装,但app-found从未发生过。即使我尝试使用instagram://app,它也会触发notfound。 - Tom Roggero
你试过将超时时间延长吗?将第95行的值从1000改为9000(只是为了好玩),然后告诉我会发生什么。 - Thiago Mata

0

1
插件无法解决当您未安装应用程序时的警报问题。 - Magico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接