30

I have a Phonegap (cordova) application where I want to load some external webpages within the phonegap WebView and I have other external webpages that I want to load in safari when the user activates them.

Typically most people have the problem where they want to open an external link in the WebView. Setting OpenAllWhitelistURLsInWebView to YES (in Cordova.plist/Phongap.plist) solves that problem.

But I don't want to open all links the the WebView, just some.

I was hoping I could just call window.open('http://someexternalsite') to open in Safari and window.parent.location.href = 'http://mysite' to open it in the WebView.

Any idea how to do this?

Lee Taylor
  • 7,761
  • 16
  • 33
  • 49
Matt
  • 1,415
  • 2
  • 15
  • 23
  • Check my 2015 answer here to open `_self` in WebView, and `_blank` in external browser: http://stackoverflow.com/questions/32208609/cordova-why-would-inappbrowser-plugin-be-required-to-open-links-in-system-brows/32227524 – Sebastien Lorber Aug 26 '15 at 13:31

10 Answers10

19

If the links you want to open in safari all contain a common string, you can use the next piece of code.

- (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSURL *url = [request URL];

    // Intercept the external http requests and forward to Safari.app
    // Otherwise forward to the PhoneGap WebView
    if ([[url scheme] isEqualToString:@"SCHEME"]) {
        [[UIApplication sharedApplication] openURL:url];
        return NO;
    }
    else {
        return [ super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType ];
    }
}

This code placed in the AppDelegate.m will open all URL that use the specified SCHEME in Safari.

I'm afraid that is all I could come up with.

Hope this helps

UPDATE :

The code should be placed in the MainViewControler, at least for cordova 2.2.0.

The method is initially commented. I had to use it to redirect Google maps links :

NSRange isGoogleMaps = [[url absoluteString] rangeOfString:@"maps.google.com" options:NSCaseInsensitiveSearch];
NSRange isGoogleTerms = [[url absoluteString] rangeOfString:@"terms_maps.html" options:NSCaseInsensitiveSearch];

if(isGoogleMaps.location != NSNotFound || isGoogleTerms.location != NSNotFound ) {
        [[UIApplication sharedApplication] openURL:url];
       return NO;
}
else 
    return [super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType];
Omaty
  • 425
  • 5
  • 14
Titouan de Bailleul
  • 12,920
  • 11
  • 66
  • 121
  • I was hoping there would be a better way but it looks like phone gap doesnt support what I'm looking for out of the box. Thanks! – Matt Mar 22 '12 at 21:49
  • i'm wanting to use this as well. Is this all you have to put in that file (and nothing in any other files) for it to work? I just want all external links `target="_blank"` to open in safari. – adamdehaven Jul 06 '12 at 01:02
  • by chance does anyone know the way to achieve this with android? – mgm8870 Jul 23 '12 at 03:02
  • if ( [request.URL.absoluteString rangeOfString:@"somedomain.com"].location != NSNotFound) { [[UIApplication sharedApplication]openURL:request.URL]; return NO; } this worked pretty well. I got the feeling from other posts that Cordova 2.0+ will support opening _blank targets in safari but haven't tested it yet. I'm starting on my android version so I'll also need to get that working. If it works I'll report back – Matt Aug 10 '12 at 21:45
  • Unfortunately, it didn't work, so I'll have to find something similar to the iOS hack for my Android version. If I figure that one out, I'll make sure to share that too – Matt Aug 16 '12 at 23:57
  • 1
    @AdamD according to the phonegap guys, your suggestion should work https://build.phonegap.com/blog/access-tags & https://build.phonegap.com/docs/config-xml/ I'm not sure why it didnt work for me, maybe because I'm using javascript window.open instead of doing it through a link. Also in that post is says if you dont add the URL to the whitelist, it will automatically open in the external browser for Android (that worked for 4.1 but not for earlier versions like 2.2 for some reason). On iOS you still need to add it to the white list in order to do anything with the url, in the webview or out. – Matt Aug 17 '12 at 00:56
  • I added an answer based on the one from @TDeBailleul that worked for me by opening any link not on my domain in the webView in a new Safari window. – adamdehaven Aug 17 '12 at 12:19
11

Just catch all links in your javascript that have target="_blank", and pass them to window.open with the '_system' param. This will work on both iOS and Android.

$(document).on('click', 'a[target="_blank"]', function(ev) {
  var url;

  ev.preventDefault();
  url = $(this).attr('href');
  window.open(url, '_system');
});
Ryan
  • 5,416
  • 1
  • 39
  • 36
  • Tested on 8.3 in the FB app, it doesn't seem to work any more. – louis.luo May 13 '15 at 18:45
  • this would be awesome if it worked, but tested on iOS 8.xx and Android 5.xx and did not work. Native seems the only way to go. – Chrispy Jul 20 '15 at 16:56
  • `_system` seems to be a feature of PhoneGap/Cordova: http://docs.phonegap.com/en/2.3.0/cordova_inappbrowser_inappbrowser.md.html#InAppBrowser – robocat Sep 13 '16 at 07:12
9

This is what works for me based on the answer by @TDeBailleul. Basically, any link that has a suffix of PDF, OR if it is a specific page I want to open in Safari, OR if it is not a page within www.example.com/* (an external link) it will open in a new window:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {

    // Open PDF files, Specific Pages, and External Links (not beginning with http://www.example.com) in Safari.app
    if (
        (navigationType == UIWebViewNavigationTypeLinkClicked) && 
        ([[[request URL] absoluteString] hasSuffix:@"pdf"] || [[[request URL] absoluteString] hasPrefix:@"http://www.example.com/specific-page.php"] || ![[[request URL] absoluteString] hasPrefix:@"http://www.example.com"])
        ) { 

        [[UIApplication sharedApplication] openURL:request.URL];
        return NO;
    } 

    return YES;
}

Hope this helps others!

adamdehaven
  • 5,890
  • 10
  • 61
  • 84
  • Yeah, that works for me too. Any luck with getting a similar thing to work for Android (2.2-present)? – Matt Aug 17 '12 at 17:17
7

You can (as of phonegap 1.5.0) use :

<a href="some://external/url" target="_blank">Click Me</a>

This should cause phonegap to launch the native browser.

I think what user868766 was referring to was that for the above to work you need the external url to be on the whitelist. The app I have been working on opened the source of news stories in the native browser so we used * in the whitelist to ensure we didnt rule out any sources.

Hope that helps.

Dan
  • 87
  • 1
  • 3
  • I tried this and it didn't seem to do anything. Rather I tried doing this in javascript and it didnt seem to do anything window.open("some://external/url", "_blank"); I also have the open all whitelist urls in webview set to true because my main application is actually a webapp, the phonegap application is just used as a login page which, when authenticated, redirects to the webapp. If the client needs to be updated it should redirect to another location (not the webapp). – Matt Aug 10 '12 at 19:14
  • @MatthewLevine You still need to allow the domains of your external URLs in your `Cordova.plist`. If you need to allow any domain then have one `ExternalHosts` entry with only `*` – Walf Sep 17 '12 at 07:55
6

The right way of doing this is using the inAppBrowser plugin

install it using the cordova CLI:

cordova plugin add org.apache.cordova.inappbrowser

Then, to open a link on safari just use:

window.open('http://apache.org', '_system');

There is a newer version of the plugin hosted on npm

to install it from the cordova CLI:

cordova plugin add cordova-plugin-inappbrowser

To open the website on safari you can use

cordova.InAppBrowser.open('http://apache.org', '_system');

or, if you want to continue using window.open like the older version you can just do this on device ready event:

document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
    window.open = cordova.InAppBrowser.open;
}
jcesarmobile
  • 51,328
  • 11
  • 132
  • 176
2

Tested on cordova 2.4 + iOS

use "_system" and no need to update any configuration

http://docs.phonegap.com/en/2.3.0/cordova_inappbrowser_inappbrowser.md.html#InAppBrowser

target: the target to load the URL in (String) (Optional, Default: "_self")

_self - opens in the Cordova WebView if url is in the white-list, else it opens in the InAppBrowser _blank - always open in the InAppBrowser _system - always open in the system web browser

Alan124
  • 31
  • 1
0

if you want to open an external url in safari, I think this is useful:
This is the %100 guaranteed solution if you are using phonegap - Tested in ios6.
to open external url in safari do following:

1-add your link in External Host (white list). e.g http://google.com
2-in Cordova.plist or Phonegap.plist, change "OpenAllWhitelistURLsInWebView" from "Yes" to "No"
3-in your application add (target="_blank") to your link
example

    <a href="http://google.com" target="_blank">Google.com</a>


Thank you.

  • 1
    Yeah, that works on iOS but not so well on android. I was hoping for a good cross platform way to do it. Hopefully the newer phonegap will fix it – Matt Nov 11 '12 at 01:15
  • 2
    "100% guaranteed solution - Tested in iOS6". I hope you recognise your flawed logic! – Ryan Jul 02 '13 at 00:02
0

This works for me it helps alot

-(void)viewDidLoad
{
   [super viewDidLoad];
    ////////////////////////
    NSString *urlAddress = @"http://www.playbuzz.org/";
    //NSURL *myURL = [NSURL URLWithString:urlAddress];
    myWebview.delegate = (id)self;
   [myWebview loadRequest:[NSURLRequest requestWithURL:[NSURL     URLWithString:urlAddress]]];
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {


    //  open External Links (not beginning with www.playbuzz.org/ in Safari.app
    if (
        (navigationType == UIWebViewNavigationTypeLinkClicked) &&
        ( ![[[request URL] absoluteString] hasPrefix:@"http://www.playbuzz.org/"])
        ) {

        [[UIApplication sharedApplication] openURL:request.URL];
        return NO;
    }

   //open Internal links in uiwebview
   return YES;
}`
Cristiana Chavez
  • 11,349
  • 5
  • 55
  • 54
0
  1. Add target="_blank" to your links. ie:

    <a href="http://www.brandonbrotsky.com/" target="_blank"></a>
    
  2. Make sure access has an origin of * /> in your config.xml (make sure its the one in the root of the app directory, above the www folder. ie:

    <access origin="*" />
    
  3. Add the following code to MainViewController.m

    - (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
    {
        NSURL *url = [request URL];
    
        // Intercept the external http requests and forward to Safari.app
        // Otherwise forward to the PhoneGap WebView
        if ([[url scheme] isEqualToString:@"http"] || [[url scheme] isEqualToString:@"https"]) {
            [[UIApplication sharedApplication] openURL:url];
            return NO;
        }
        else {
            return [ super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType ];
        }
    } 
    

I made a quick video explaining how to fix this issue:

http://www.youtube.com/watch?v=zqbjXSnAR-Q&feature=c4-overview&list=UUefS6KLvFQVjhmL6hiBq4Sg

Hope it helps!

0

iside the xcode

//Place code in /Classes/MainViewController.m

    - (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)­navigationType
{ NSURL *url = [request URL]; 
// Intercept the external http requests and forward to Safari.app 
// Otherwise forward to the PhoneGap WebView 
if ([[url scheme] isEqualToString:@"http"] || [[url scheme] isEqualToString:@"https"]) { [[UIApplication sharedApplication] openURL:url]; return NO; } else { return [ super webView:theWebView shouldStartLoadWithRequest:request navigationType:navigationType ]; }
}
Lobo
  • 1