Launching app OR app store from Safari?

68,072

Solution 1

It's not possible to check if app is installed from a web page. You could do it inside an other app by checking if your url scheme can be opened using UIApplication's -canOpenURL: method, but there is no javascript equivalent to this.

However, you can use the following workaround:

<script language="javascript">
    function open_appstore() {
        window.location='http://itunes.com/';
    }

    function try_to_open_app() {
        setTimeout('open_appstore()', 300);
    }
</script>

<a onClick="javascript:try_to_open_app();" href="yourappurl:">App name</a>

This code will set a timeout on the link that will call the open_appstore function if this timeout ends. Since your link is pointed at the app's custom url, Safari will try to open that link and if it can, it will open the app and stop the timer, so AppStore link will not be opened.

If the app link can't be opened, when timer runs out it will display an error popup saying it can't open the page (can't get rid of that), but it will immediately go to AppStore and dismiss that error.


iOS 9 adds a really nice feature that lets your app open a http/s url: Universal Links


In iOS 10 there is a popup saying "Open in [App Name]" when you tap the link and the app is installed. If the user does not tap on "Open" in the given timeout, this solution will use the fallback. As 300ms is too short to tap anything, this solution always fails on iOS 10.

Solution 2

This worked for me with a similar situation: wherein I wanted to open gmaps app if it was supported - otherwise go to gmap site directly.

function mapLink(addy) {     
  addy = encodeURIComponent(addy);

  var fallback = 'http://maps.google.com/?q=' + addy
  , link = 'comgooglemaps://?q=' + addy;

  try {
    document.location = link;
  } catch(err) {
    document.location = fallback;
  }
}

Seems to work pretty well for my use case.

Update: If you want to do a new window on fallback, this still allowed the ios error message to pop up. To get around it try this.

  try {
    document.location = link;
  } catch(err) {
    window.location.reload(true);
    window.open(fallback, '_blank');
  }

Solution 3

The Solution from Apple:

From Apple Documentation

https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/PromotingAppswithAppBanners/PromotingAppswithAppBanners.html

If the app is already installed on a user's device, the banner intelligently changes its action, and tapping the banner will simply open the app. If the user doesn’t have your app on his device, tapping on the banner will take him to the app’s entry in the App Store. When he returns to your website, a progress bar appears in the banner, indicating how much longer the download will take to complete. When the app finishes downloading, the View button changes to an Open button, and tapping the banner will open the app while preserving the user’s context from your website.

Smart App Banners automatically determine whether the app is supported on the user’s device. If the device loading the banner does not support your app, or if your app is not available in the user's location, the banner will not display.

To add a Smart App Banner to our webpage, include the following meta tag in the head of each page where you’d like the banner to appear:

NOTE: We can also pass the app-argument: like myName,etc.,

Check that Providing Navigational Context to Your App Header in this Page

Updates:

1. Once you have closed the banner that showing up, then that will not be displayed again even though you had that meta tag in our html.

2. To reset that launch the settings App then navigate to General>Resent>Reset all settings

Solution 4

You can simply read the return value from the method -(BOOL)openURL:(NSURL)url*, if it's NO, it means that the target application isn't installed. Following code snipped gives an example using the navigon url scheme:

NSString *stringURL = @"navigon://coordinate/NaviCard/19.084443/47.573305";
NSURL *url = [NSURL URLWithString:stringURL];
if([[UIApplication sharedApplication] openURL:url]) {
    NSLog(@"Well done!");
} else {
    stringURL = @"https://itunes.apple.com/it/app/id320279293?mt=8";
    url = [NSURL URLWithString:stringURL];
    [[UIApplication sharedApplication] openURL:url];
}

Thanks to zszen for the correction.

Share:
68,072
ninjaneer
Author by

ninjaneer

Updated on March 08, 2020

Comments

  • ninjaneer
    ninjaneer about 4 years

    I already know how to launch an app from safari, but is it possible to check if the app is installed before launching? I'm thinking to launch the app store if the app isn't currently installed on the iPhone.

  • George
    George almost 12 years
    I tried this. However, if the "yourappurl:" successfully launches your app, then when the user returns to Safari the timeout will eventually fire anyway and send the user to itunes.
  • Filip Radelic
    Filip Radelic almost 12 years
    @George In what version of iOS and on what device is this happening?
  • TheSquad
    TheSquad over 10 years
    Have some downsides, however right now, is the best solution I found... +1
  • einstein
    einstein over 10 years
    @George You can clear the time out. So when he comes back nothing happens
  • Thayne
    Thayne over 10 years
    This still shows the warning saying "Cannot Open Page". Is there any way to prevent this from happening. Also, I would like to remain on the same page rather than redirecting if the app isn't installed.
  • Rick
    Rick over 9 years
    Did you mean that you are doing this? try {document.location=link;} catch(x) {document.location=fallback;}
  • Logger
    Logger over 9 years
    @Filip Radelic. How to use this code in Objective c. I mean when i am sending mail using MailController
  • Nicos Karalis
    Nicos Karalis over 9 years
    Just a small update, your code does still work in Mac OS, awesome.. ty
  • zszen
    zszen over 9 years
    itunes.apple.com/it/app/id320279293?mt=8 Removed app name it can work well.
  • Hemang
    Hemang about 9 years
    @ReddyBasha, in iOS MFMailComposeViewController has a method canSendMail. And you should check it like this, if([MFMailComposeViewController canSendMail]) {...}
  • Brian Cannard
    Brian Cannard almost 9 years
    The code will work on any OS which supports system-wide URI protocol handlers. Windows, OS X, iOS, Android, Linux.
  • baquiax
    baquiax over 8 years
    That's cool, but by example: I need do the same thing that Smart Banners does, with the difference that I need n numbers of links with different deep links. I understand that I can add some more data to Smart Banner but the link of Smart Banner is unique for page. If you have any idea, its graceful received!
  • rplankenhorn
    rplankenhorn over 8 years
    This code won't work for iOS 9. It won't ever hit the catch block because the link url will fail silently if the app isn't installed.
  • Rotem
    Rotem about 8 years
    Universal Links solution is what I was looking for!
  • iplus26
    iplus26 over 7 years
    As @Thayne said, there'll be a popup confirm saying "Cannot Open Page", at least there'll be in iOS 9. Isn't it happen in iOS 8 or earlier versions? Any solutions to prevent that?
  • r-dent
    r-dent about 7 years
    in iOS 10 there is a popup saying "Open in [App Name]" when the app is installed. If the user does not tap on "open" in the given timeout, this solution will use the fallback. As 300ms is too short to tap anything, this solution always fails. In my opinion, the answer should mention this.
  • Filip Radelic
    Filip Radelic about 7 years
    @r-dent you are right, feel free to edit the answer :)