Check if URL scheme is supported in javascript

77,781

Solution 1

No, not from a webpage.

Solution 2

Not seamlessly. But there is a way similar to checking if a pop-up was blocked or not.

When you try a URL scheme which is not supported, Safari will warn the user that it doesn't know what to do with it and stay on the same page.

So if you gave your app-call some time to activate, say 300 ms, and then do something else to respond to the non-existence of the scheme.

It's not the prettiest but it works:

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>

Solution 3

Here is a solution that does not show the popup when you come back from the app, it assumes you've been gone longer than 400 ms:

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

Solution 4

I found pagehide event to be more robust than depending on system time. For those of us who prefers a non-jQuery favor, here is the snippet.

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

Solution 5

Another great (at least working in latest browser versions) workaround is to check if the browser window has focus after a short timeout, this way you can show a dialog box to the user only if the URI scheme didn't work

HTML:

<a class="uri-link" data-uri="qobuzapp://" href="#">URI</a>​

Javascript (using jQuery here):

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')); 
});​
Share:
77,781
Admin
Author by

Admin

Updated on January 01, 2020

Comments

  • Admin
    Admin over 4 years

    Is there any way to check if a URL scheme is currently registered on the phone... with javascript?

  • Jakob Dam Jensen
    Jakob Dam Jensen about 15 years
    I thought I recalled a way that apps could check this but I'm probably wrong.
  • Admin
    Admin about 15 years
    Thanks for the quick answer. As far as from native code, it is possible via openUrl: to check, so I've read... not tested
  • samvermette
    samvermette about 13 years
    It was worth a try, but indeed this is kinda a nasty solution. That function gets called even if the URL scheme goes through when you come back to the page. So the user gets an alert popup no matter what. Either 1 or 2, depending on whether his device support the scheme.
  • Di Wu
    Di Wu about 13 years
    @Brent Royal-Gordon: Nope. A native iPhone app can check by calling canOpenURL:.
  • amok
    amok almost 13 years
    There's a way from a web page: stackoverflow.com/questions/1108693/…
  • Amir
    Amir almost 13 years
    @samvermette There is a semi-complicated workaround. If the url scheme works, then have your app send a confirmation to your server. Then when you come back to the app, have it ping the server to see if the app was opened successfully. Complicated, but feasible.
  • Underdog
    Underdog almost 12 years
  • devios1
    devios1 almost 11 years
    Is there any way to not show that horribly unfriendly error if the app is not installed?
  • Magico
    Magico about 10 years
    The plugin does not solve the problem of the alert when you DO NO have the app installed
  • JoshNaro
    JoshNaro about 10 years
    We've run into a problem where the "now" variable in this solution is flat out wrong. We can wait minutes in the app, go back to the browser, and get the confirmation. It seems the hibernation wakeup process is buggy.
  • funkybro
    funkybro about 9 years
    This is one of those "factually correct, but not actually that useful" answers. This answer addresses the question the OP probably ought to have asked in the first place!
  • Tom Roggero
    Tom Roggero about 9 years
    nice concept. although the app-found doesn't happen ever. Even when the app is installed (i tried instagram://app) it triggers the notfound one.
  • Thiago Mata
    Thiago Mata about 9 years
    Do you tried to make the timeout bigger? Change the value in line 95 from 1000 to 9000 ( just for fun ) and tell me what happens.
  • diachedelic
    diachedelic about 4 years
    iOS 13.3 solution which plays nice with the "horribly unfriendly error": gist.github.com/diachedelic/0d60233dab3dcae3215da8a4dfdcd434
  • jstuardo
    jstuardo over 3 years
    That code does not work. When the schema exists and it is associated with an executable, browser asks if one wants to run that app. That delay causes the timeout to arrive and obviously, the confirm function to be executed.
  • jstuardo
    jstuardo over 3 years
    That code does not work. When the schema exists and it is associated with an executable, browser asks if one wants to run that app. That delay causes the timeout to arrive and obviously, the confirm function to be executed.