18

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

  • Changing the scope in the manifest-file
  • Using rel="noreferrer"
  • Using target="_blank"
Viktor Belashov
  • 361
  • 1
  • 2
  • 12
  • 2
    I have the same problem with safari, I want to use cameraAPI in another link but in Standalone mode, I can't access the camera – Mohammad Sadegh Foroughi Feb 21 '20 at 09:17
  • I found a workaround but it's lame. Removing the "standalone" from my manifest to prevent my PWA from opening as PWA!!! Did you find any solutions? @Victor-Belashov – Mohsen Feb 21 '20 at 09:29
  • Is this a "PWA" that's using cordova to wrap your web app? Like you get with PWABuilder. – markdon Feb 24 '20 at 01:12
  • What happens if you use `target="_blank` on the `href`? I don't have a device to test. I assume the chromeless PWA window couldn't handle that request and it might trigger Safari. – Bryce Howitson Feb 24 '20 at 19:49
  • 1
    @BryceHowitson `target="_blank"` will still use the in-app browser instead of opening in the normal safari view. – Jens Væver Hartfelt Nov 17 '20 at 11:52
  • Did you find a solution? I am having the exact same problem (migrating users from an old ios web app to a pwa on another domain). I want to open the new pwa in safari and let the users add it to their homescreen right away but this way the users will get the in-app safari then they have to click the tiny safari icon in the bottom-drawer and then add it to homescreen from there. – Jens Væver Hartfelt Nov 17 '20 at 11:57

7 Answers7

2

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.

Bryce Howitson
  • 7,339
  • 18
  • 40
  • 1
    These are some really good suggestions! Unfortunately `window.open` and `window.location.href` both opens the in-app browser. I don't fully understand what you mean by setting `content="no"`. If done on the page you're linking from then this page would stop being in fullscreen mode (at least if safari ever recognises that you made this change). If you set it on the page you're linking to that page will stop being an fullscreen app which defeats the whole purpose. – Jens Væver Hartfelt Nov 19 '20 at 08:45
  • About the URL-scheme i really thought this would be a way to work around this, but it seems there is no URL-scheme for safari: https://stackoverflow.com/a/22644889/7446618 – Jens Væver Hartfelt Nov 19 '20 at 08:46
  • @JensVæverHartfelt I think you should ask a new question that fully describes your use case. It's difficult to help you when you may or may not need the same thing as the OP. – Bryce Howitson Nov 19 '20 at 22:43
  • I appreciate your feedback, but OP's problem is the exact same as mine so a new question would just duplicate the same content. I have edited OP's question to be a bit more concise and added some of the suggested solutions that doesn't resolve the issue. I've also added a workaround as an answer. – Jens Væver Hartfelt Nov 23 '20 at 09:20
  • @JensVæverHartfelt The confusing part is that you keep saying PWA and "in-app browser" together. PWA's by definition are web apps that run INSIDE Safari even if they're "installed". So the answers are confusing. For example, `target="_blank"` very much DOES break an HTML page out of a web view shipped inside a native iOS app. But that doesn't seem like your scenario. – Bryce Howitson Nov 23 '20 at 17:31
  • 3
    Well i don't know how to further clarify it. Maybe by adding images to OP's original question? Target="_blank" sounds great for native apps, but they don't behave the same from PWA's on iOS. By PWA i am referring to an installed PWA opened from the home screen on iOS. By in-app browser i am referring to the browsing mode used when opening ANY link to external domains from within a PWA. Go to the heading "Opening links using Safari is impossible" in this article: https://medium.com/@firt/whats-new-on-ios-12-2-for-progressive-web-apps-75c348f8e945 to see what i mean. – Jens Væver Hartfelt Nov 24 '20 at 20:21
1

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

  • The isIOSInAppBrowser function does not work for me. When I open it in and in-app browser it returns false. iOS 14.2 – Ziyak Dec 24 '20 at 09:10
  • Oh.. Maybe they've changed this behaviour after 14.1. I will try it out and see if i get similar results – Jens Væver Hartfelt Jan 11 '21 at 08:01
  • I just tested it and it does seem to work for me on 14.1 and 14.3 (i don't have a 14.2 simulator to test with currently), but keep in mind that it only handles the rather niche-case of when a full-screen web app (pwa or legacy home screen app) is running an in-app-browser on top of it. I haven't tested it for in-app-browsers outside of this scope – Jens Væver Hartfelt Jan 26 '21 at 12:43
0

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()
  • Please provide an explanation to your code - it is very hard to understand something when it isn't explained. – ethry Jul 02 '22 at 21:20
-2

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.

Adriano
  • 3,788
  • 5
  • 32
  • 53
liviu blidar
  • 351
  • 4
  • 16
  • Thta's not true since iOS12.2 – Fabio Ricci Nov 03 '20 at 15:26
  • Neither `rel` or `target` has any effect on this. The scope in the manifest file will control wether the links open with the in-app browser or as standalone "chrome-less" pages, but it doesn't have any effect over whether links open in in-app safari og regular safari – Jens Væver Hartfelt Nov 17 '20 at 12:01
-2

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"
}
dhamo dharan
  • 712
  • 1
  • 10
  • 25
-2
@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)
}
DAG
  • 6,710
  • 4
  • 39
  • 63
-3

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>
devwk
  • 372
  • 2
  • 14
  • 1
    This might work in some, but not recent ones, where you're still stuck in their dysfunctional in app browser. There are possibly some upsides to this (sharing context so as to permit oauth to work), but it breaks on other things (external links on external sites do not work) - it would be useful to have control over this instead, so that you can use the in app for oauth and functional one for others. – El Yobo May 21 '20 at 06:13
  • your comment is incorrect. this should work just fine on all devices – devwk May 23 '20 at 19:29
  • 1
    Unfortunately not; modern iOS sticks you in the in app browser instead, which you're possibly mistaking for Safari but it's not quite the same. My external links on external sites comment is incorrect though; links in the in app browser that use `target="_blank"` do not work (the in app browser seems to be limited to a single window), but other links do, which means you can work around it if you control the external site you're linking to. – El Yobo May 24 '20 at 23:50
  • i am not mistaken. the question was for Progressive Web Applications not an app – devwk May 25 '20 at 04:44
  • 3
    Yeah, my answers are for a PWA also. [This article](https://medium.com/@firt/pwas-on-ios-12-2-beta-the-good-the-bad-and-the-not-sure-yet-if-good-a37b6fa6afbf) may provide some context. Your answer may have been correct at one point in time, and may still be correct for older iOS versions, however it is incorrect for more up to date versions. – El Yobo May 26 '20 at 00:54