Viktor Belashov
Viktor Belashov

Reputation: 411

ios PWA How to open external link on mobile default safari(not In app browser)

I'm making a PWA in IOS 13.2.

I need to launch another PWA from my app by clicking an external link.

The problem is that my current PWA opens all external links in the in-app browser instead of regular safari and there is no add to Home screen option in the in-app browser.

How can I force the PWA to open an external link in regular safari instead of in-app safari?

Things that doesn't work

Upvotes: 21

Views: 22835

Answers (8)

Victor Trusov
Victor Trusov

Reputation: 1222

Works only in iOS 17, I couldn't find a way to do it in earlier versions of iOS.

window.location = `x-safari-${window.location.href}`;

So the URL should look like x-safari-https://domain

It looks like the in-app browser also blocks the second attempt (if a user clicks 'don't open safari' the first time), so rendering a link with this URL instead might be a better solution.

Upvotes: 3

Julio Diniz
Julio Diniz

Reputation: 21

Tested with latest iOS-12/iPhone 7

If anyone could test with different device and iOS versions.

iOS is opening <a> tag as external url, launching Safari.

So, create a hidden tag:

HTML
<a hidden id='openSafari' href=''>click me</a>

script
let openSafari = document.getElementById('openSafari');
openSafari.setAttribute('href', 'https://netflix.com');
openSafari.click()

Upvotes: -1

Bryce Howitson
Bryce Howitson

Reputation: 7710

It's a bit hard to answer this question (and all the comments) as the use case isn't overly clear, but here goes...

On mobile devices, an "in-app browser" is NOT the same thing as a Progressive Web App running in full-screen mode.

If an iOS app runs and then displays HTML content inside of it, it's utilizing UIWebView or WKWebView. However, in the case of a PWA it's already running in Safari as a "full screen" experience. Defining which you're trying to break links out of is extremely important as they function differently.

target="_blank" will typically break a link out of a page using WebView. I believe this is the default functionality for links outside the current domain as well.

An "installed" PWA is running in something called "Stand Alone" mode. This makes it full screen and removes navbars, etc. As of this writing, Safari doesn't support the fullscreen API that other browsers are implementing. Chrome uses the App manifest file to determine this functionality. Safari basically ignores the manifest in favor of proprietary meta tags.

In this case <meta name="apple-mobile-web-app-capable" content="yes"> tells Apple to make the page a stand-alone app. Try setting content="no" (Safari caches things heavily so you might need to force a refresh) on the pages that should break out of stand-alone mode. You can check to see what mode the page thinks it's in by using this javascript boolean window.navigator.standalone.

Or you can use javascript to force a "new window" in Safari as long as you're targeting a different subdomain or HTTP instead of HTTPS.

// if app is hosted from https://example.com
if (("standalone" in window.navigator) || window.navigator.standalone ) {
    window.open('http://example.com/page', '_blank');
}

Finally, Apple uses some special URL strings to cause native apps to handle some actions like emails, phone numbers, and youtube videos. You might be able to "hack" that functionality to get safari to open your link.

Upvotes: 2

After quite thorough investigations i believe this isn't possible currently (between iOS 13.X and iOS 14.1).

The following javascript API's will use in-app browser:

  • window.open()
  • window.location.href =

Using an anchor tag will also use the in-app browser no matter what attributes it is assigned. Changing the scope in the manifest also doesn't help.

BUT i did find a way to at least prompt the user that they are in an in-app browser to make the UX a little less confusing.

There are two ways (maybe more?) to detect if the browser is standalone: window.matchMedia("(display-mode: standalone)").matches and window.navigator.standalone . And here is the weird part:

// regular safari
window.navigator.standalone -> false
window.matchMedia("(display-mode: standalone)").matches -> false

// full screen apps (only pwas, weirdly enough this doesn't apply to pre-pwa web apps on iOS)
window.navigator.standalone -> true
window.matchMedia("(display-mode: standalone)").matches -> true

// in-app browsers launched from within a PWA 
window.navigator.standalone -> true
window.matchMedia("(display-mode: standalone)").matches -> false

I assume window.navigator.standalone represents the parent context of the pwa and window.matchMedia("(display-mode: standalone)").matches represents the context of the in-app browser.

So a naive implemention to check if your app is running in the in-app browser on iOS:

function isIOSInAppBrowser() {
  // Check if device is iPad, iPhone or iPod (this bit is naive and should probably check additional stuff)
  if (Boolean(window.navigator.userAgent.match(/iPad|iPhone|iPod/)) === false) return false;

  // Check if navigator is standalone but display-mode isn't
  if (window.navigator.standalone === true && window.matchMedia("(display-mode: standalone)").matches === false) {
    return true;
  } else {
    return false;
  }
}

note that this implementation isn't reliable and can easily produce false positive in future version of iOS

Upvotes: 2

Shubham Raj
Shubham Raj

Reputation: 9

@IBAction func openURL(_ sender: Any) {
// check if website exists
guard let url = URL(string: "https://apple.com") else {
    return
}

let safariVC = SFSafariViewController(url: url)
    present(safariVC, animated: true, completion: nil)
}

Upvotes: -2

liviu blidar
liviu blidar

Reputation: 361

I would personally try the target="_blank" to the href link. I would also add a rel="noreferrer external" to ensure this is consistent across different webview implementations. There should also be a way to do this via the manifest file although I'm not entirely sure how that works in iOS.

Upvotes: -2

devwk
devwk

Reputation: 368

This will work perfectly on all iOS versions with PWA support. (I know this because I am a longtime iOS user):

Add target="_blank" to all the links that you have. That will open them in the mobile default safari.

For example:

<a href="/page" target="_blank">Page</a>

Upvotes: -4

dhamo dharan
dhamo dharan

Reputation: 762

The way your app will work based on what did you configured in manifest.json file.

In manifest file the scope key will determines which link will open inside PWA and which link will open in browser.

For example route under myapp will open inside PWA and other would be outside.

{
  "name": "My App",
  "start_url": "/myapp",
  "scope": "/myapp",
  "display": "standalone"
}

Upvotes: -2

Related Questions