如何在Safari中打开外部链接而不是应用程序的UIWebView?

30

我有一个Phonegap(cordova)应用程序,在其中想要在phonegap WebView中加载一些外部网页,而我还有其他外部网页,当用户激活它们时,我想在safari中加载它们。

通常,大多数人都遇到这样的问题,即希望在WebView中打开外部链接。将OpenAllWhitelistURLsInWebView设置为YES(在Cordova.plist / Phongap.plist中)可以解决该问题。

但是我不想在WebView中打开所有链接,只想打开其中一些。

我希望我只需调用window.open('http://someexternalsite')以在Safari中打开,而使用window.parent.location.href = 'http://mysite'则能在WebView中打开。

您有任何想法如何实现吗?


请查看2015年我的答案,了解如何在WebView中使用"_self"打开链接,在外部浏览器中使用"_blank":https://dev59.com/71wY5IYBdhLWcg3wyqWH#32227524 - Sebastien Lorber
10个回答

19

如果您想在 Safari 中打开的链接都包含一个共同的字符串,您可以使用下面的代码。

- (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 ];
    }
}

将此代码放置在AppDelegate.m中,将会在Safari中打开所有使用指定协议的URL。

恐怕这就是我能想到的全部了。

希望这有所帮助。

更新:

对于cordova 2.2.0,应将该代码放置在MainViewControler中。

该方法最初是注释掉的。我不得不使用它来重定向Google地图链接:

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];

我也想使用这个。这是你需要放在那个文件中的全部内容吗(其他文件中没有任何内容)才能使它工作?我只想让所有外部链接target="_blank"在Safari中打开。 - adamdehaven
如果([request.URL.absoluteString rangeOfString:@"somedomain.com"].location != NSNotFound){ [[UIApplication sharedApplication]openURL:request.URL]; 返回NO; } 这个运行得非常好。我从其他帖子中感觉到 Cordova 2.0+ 将支持在 Safari 中打开 _blank 目标,但尚未测试。我正在开始我的 Android 版本,所以我也需要让它工作。如果成功了,我会回报的。 - Matt
不幸的是,它没有起作用,所以我必须为我的Android版本找到类似于iOS hack的东西。如果我弄清楚了那个问题,我一定会分享出来。 - Matt
1
@AdamD 根据PhoneGap的人说,你的建议应该是可行的 https://build.phonegap.com/blog/access-tags 和 https://build.phonegap.com/docs/config-xml/。我不确定为什么对我没有起作用,可能是因为我使用了javascript window.open而不是通过链接来实现。此外,在那篇文章中还说,如果您没有将URL添加到白名单中,则Android会自动在外部浏览器中打开它(这适用于4.1但不适用于早期版本,如2.2,原因不明)。在iOS上,您仍然需要将其添加到白名单中才能在webview或其他地方处理URL。 - Matt
我添加了一个答案,基于@TDeBailleul的答案,并通过在新的Safari窗口中打开任何不在我的域上的链接来使其对我有效。 - adamdehaven
显示剩余2条评论

11

只需在您的JavaScript中捕获所有具有target="_blank"的链接,并将它们传递给带有“_system”参数的window.open。 这适用于iOS和Android。

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

  ev.preventDefault();
  url = $(this).attr('href');
  window.open(url, '_system');
});

测试了在 FB 应用中的8.3版本,似乎不再起作用。 - louis.luo
如果这个能够正常工作的话就太棒了,但是在 iOS 8.xx 和 Android 5.xx 上测试过并没有成功。似乎本地化是唯一可行的方式。 - Chrispy
"_system"似乎是PhoneGap/Cordova的一个特性:http://docs.phonegap.com/en/2.3.0/cordova_inappbrowser_inappbrowser.md.html#InAppBrowser - robocat

9

这是基于@TDeBailleul的答案对我有效的操作。基本上,任何链接如果有PDF后缀、或者如果它是我想在Safari中打开的特定页面、或者它不是www.example.com/*内的页面(即外部链接),都会在新窗口中打开:

- (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;
}

希望这能帮助其他人!

对我来说也可以。你有没有在Android(2.2至今)上实现类似的功能的好运? - Matt

7

从PhoneGap 1.5.0版本开始,您可以使用以下内容:

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

这应该会导致PhoneGap启动本地浏览器。

我认为用户868766所指的是,为了使上述内容起作用,您需要将外部URL列入白名单。 我一直在开发的应用程序中,使用*在白名单中打开新闻故事的源,以确保我们不排除任何来源。

希望这有所帮助。


我尝试过这个,但似乎没有任何反应。相反,我尝试在JavaScript中执行此操作,但似乎也没有任何反应。window.open("some://external/url", "_blank");我还将所有白名单URL在Webview中打开的设置设置为true,因为我的主要应用程序实际上是一个Web应用程序,PhoneGap应用程序仅用作登录页面,当验证通过时,重定向到Web应用程序。如果需要更新客户端,则应重定向到另一个位置(而不是Web应用程序)。 - Matt
@MatthewLevine,你仍然需要在你的Cordova.plist中允许外部URL的域名。如果你需要允许任何域名,则只需使用一个ExternalHosts条目,并且将其设置为 * - Walf

6

正确的做法是使用inAppBrowser插件

使用cordova CLI安装:

cordova plugin add org.apache.cordova.inappbrowser

然后,要在Safari中打开链接,只需使用以下方法:

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

在npm上托管了一个插件的新版本

要从cordova CLI安装它:

cordova plugin add cordova-plugin-inappbrowser

在Safari浏览器中打开网站,您可以使用

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

或者,如果您想继续使用类似旧版本的window.open,您可以在设备就绪事件上执行以下操作:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
    window.open = cordova.InAppBrowser.open;
}

2

1
嗨,我正在使用 _system,代码如下:window.open(gameOverLink, '_system'); 但是它对我不起作用。请建议。 - User16119012

0

在Xcode中

//将代码放置于/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 ]; }
}

0

如果你想在Safari中打开一个外部链接,我认为这个方法很有用:
如果你使用Phonegap,并且测试过iOS6,那么这是100%保证的解决方案。
打开Safari中的外部链接,请按照以下步骤进行操作:

1-将你的链接添加到External Host(白名单)中。例如:http://google.com
2-在Cordova.plist或Phonegap.plist中,将"OpenAllWhitelistURLsInWebView"从"Yes"改为"No"
3-在你的应用程序中,在你的链接中添加(target="_blank")
例如

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


谢谢。


1
是的,这在iOS上可以工作,但在Android上效果不太好。我希望有一个良好的跨平台方法来解决它。希望新的PhoneGap可以解决这个问题。 - Matt
2
"100%保证解决方案 - 已在iOS6中进行测试。希望你认识到你错误的逻辑!" - Ryan

0

这对我很有帮助,它能够很好地解决问题。

-(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;
}`

0
  1. 在您的链接中添加 target="_blank" 属性。 例如:

    <a href="http://www.brandonbrotsky.com/" target="_blank"></a>
    
  2. 在 config.xml 文件中,确保 access 具有 * /> 的来源(确保它是应用程序目录根目录中的一个,在 www 文件夹上面)。 例如:

    <access origin="*" />
    
  3. 将以下代码添加到 MainViewController.m 中:

    - (BOOL)webView:(UIWebView *)theWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
    {
        NSURL *url = [request URL];
    
        // 拦截外部 http 请求并转发到 Safari.app
        // 否则转发到 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 ];
        }
    } 
    
我制作了一个快速的视频,解释如何修复这个问题。

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

希望能对你有所帮助!


请在此处提供所描述的答案,然后附上链接。仅发布链接将被标记为垃圾邮件。 - Habibillah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接