Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doesn't work on iOS 9 #16

Closed
sgtpepper43 opened this issue Sep 17, 2015 · 19 comments
Closed

Doesn't work on iOS 9 #16

sgtpepper43 opened this issue Sep 17, 2015 · 19 comments

Comments

@sgtpepper43
Copy link

Trying to open the link always fails on iOS 9, whether you have the app or not.

@ohh2ahh
Copy link

ohh2ahh commented Sep 17, 2015

I can confirm that it doesn't work on iOS 9. Works fine on iOS 8.4.1.

It seems that the following doesn't get executed:

iframe.onload = function() {
  clearTimeout(timeout);
  iframe.parentNode.removeChild(iframe);
  window.location.href = uri;
};

@stefangomez
Copy link

iOS 9 added privacy features where apps can't navigate or "detect" apps installed --assuming this affected safari as well :/

having a link like <a href="deeplink://destination">link</a> works though.

@sgtpepper43
Copy link
Author

Even just assigning window.location works. It seems that after all the effort of introducing their new "Universal Links" thing that automatically checks if an app exists for links between different apps, they decided doing the same thing for Safari was not something they wanted to pursue... I guess.

@shailendher
Copy link

The below approach fixes this issue:
mderazon/node-deeplink#8
but creates new one:
mderazon/node-deeplink#9

@omihailo
Copy link

Can we expect fixing of this issue soon?
The users are migrating to iOS 9 very fast, so we are already experiencing some issues with it.
There are apps which really depends on the deeplink script.

@lukasnagl
Copy link

lukasnagl commented Sep 23, 2015

@omihailo As @sgtpepper43 already mentioned, Apple likely expects you to implement universal links (see the WWDC talk).

As long as your app is not an app launcher or something, implementing universal links is likely the way to go, since Apple seems to conceptually treat hitting Safari as the “no deeplink recognized” fallback. Differently stated: Safari conceptually doesn’t expect automatically triggered deeplinks, since universal links are recognized before the page is fully loaded in Safari.

@kennyth01
Copy link

as @shailu highlighted, here's the quick fix for this issue:
go to line 188 replace and use the snippet below:

var ua = window.navigator.userAgent;
        if (ua.match(/CriOS/) || (ua.match(/Safari/) && ua.match(/Version\/9/))) {
            //do another approach...
            document.location = uri;
        } else {
            var iframe = document.createElement("iframe");
            iframe.onload = function() {
                clearTimeout(timeout);
                iframe.parentNode.removeChild(iframe);
                window.location.href = uri;
            };
            iframe.src = uri;
            iframe.setAttribute("style", "display:none;");
            document.body.appendChild(iframe);
        }

@andyvb
Copy link

andyvb commented Sep 30, 2015

@kennyth01, unfortunately as @shailu mentioned, the workaround causes an error dialog to appear if the user doesn't have your app installed. Unfortunately that's a non-starter for us. The only real solution for us is to use Universal Links.

@kennyth01
Copy link

@andyvb what do you mean by "error" dialog? I didn't saw any error dialog?

Edited: saw it already, disregard this post. But I think it should be okay to have that for as long as you combine deep-linking with a custom smart app banner.

@andyvb
Copy link

andyvb commented Oct 2, 2015

@kennyth01 It's in the ticket shailu linked to (mderazon/node-deeplink#9). You see this dialog if you don't have the app installed:
safari_canot_open_page

Edited: There's no way to absolutely prevent the user from seeing that dialog regardless whether you have a smart app banner. The slightly better UX is to trigger the script from some user interaction like when they tap a button on the web page like, "hey open the page in my app". The problem is they'll see the error dialog if you don't have the app installed. There is no workaround with pure Javascript to 100% prevent the error dialog.

The best UX that supports deep linking across iOS versions is:

  1. On iOS 8 and older, keep using this script.
  2. On iOS 9, implement Universal Links. Do not use document.location.

@kopiro
Copy link

kopiro commented Oct 18, 2015

The best solution I found is to:

location.href = DEEP_LINK
location.href = FALLBACK_LINK

With this solution, if the app is not installed, an error dialog is thrown, but after clicking OK another dialog appear with the question "Open App store?".


I print also a small HTML with a link to the fallback, in the case the user clicks "Cancel" of the dialogs.

@mderazon
Copy link

ios 9.2 has made things worse. see this blog post

@shailendher
Copy link

From the link:

"What changed in iOS 9.2?

Apple changed the 'Open App' modal from a blocking modal to a non blocking modal. When you try to >open up the app, the modal will no longer block Javascript from executing, meaning that the fallback >redirect to the App Store will execute immediately before the user can click 'Open App'."

Wasn't this the case even in ios 9.0?

@leonyu
Copy link

leonyu commented Dec 21, 2015

In iOS 9.0, setting a new URL after the "non-blocking modal" cause the dialog box to be dismissed as if user clicked "Open", which is useful behavior.

In 9.1, the app launch dialog box is blocking, while the error dialog box is non-blocking.

In 9.2, both dialog boxes are non-block. Also setting a new URL causes dialog box to be dismissed as if user clicked "Cancel", which is does not help the cause.

@robindra
Copy link

robindra commented Jul 4, 2016

@kopiro: Is there any way to detect user click on cancel button in the popup so that we can directly redirect to the fallback url without printing the small html page.

@kopiro
Copy link

kopiro commented Jul 4, 2016

I think you cant, it's an OS dialog you can't just control.

@leonyu
Copy link

leonyu commented Jul 4, 2016

For user action, you can guess using requestAnimationFrame. Due to the fact that both dialog box and app switching takes up more GPU than scrolling a page, the timing difference between successive requestAnimationFrame could be used to differentiate various user actions. It is fairly complicated and requires benchmarking to get any meaningful result, so it is not worthwhile for most uses, since you can't use it to tell if app is installed or not.

Also there is slight difference in window.open('customURL://blah') on 9.2 between having the app and not having the app. If the app exists, the popup would close automatically when user cancel, if the app doesn't exist, the popup would stay. This may be used to detect if user has the app installed if we preemptively open and close a pop-up. However, given the horrid user experience that would entail, I didn't bother investigating further. No clue if it is still the case in 9.3 or 10.

@albandaft
Copy link

@leonyu this could be a nice hack (but apple is annoying with this changes....)

@sgtpepper43
Copy link
Author

I'm closing this because it's been three years and I don't want to see this in my issues list anymore 😁 Plus as of b0bd1cf this project is no longer maintained.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests