PhoneGap InAppBrowser: 打开iOS Safari浏览器

4

在我们的PhoneGap iOS应用中,我们使用InAppBrowser插件来展示一些内容,并且我们需要从InAppBrowser中打开Safari浏览器。

我们该如何使得在InAppBrowser中的链接能够在Safari中打开?


如果你更加具体,你就更可能得到答案。你需要什么时候打开Safari?是因为用户的操作还是其他原因?请详细阐述你的问题。 - Greg
从InAppBrowser中,我想在Safari浏览器中打开外部链接。我能够使用以下代码打开Safari浏览器。但是在InAppBrowser中,同样的链接也会被打开。function iabLoadStart(event) { console.log("iabLoadStart: " + event.type + ' - ' + event.url); if (event.url.indexOf("openinSafari") != -1) { window.open(event.url, '_system');
} }
- Vilas M.
如果你能够打开Safari,那么问题究竟是什么? - Greg
但是同一个链接在InAppBrowser和Safari浏览器中都打开了。但它应该在Safari浏览器中打开,而不是在InAppBrowser中打开。 - Vilas M.
在函数中的任何检查或打开Safari之前,首先尝试调用event.preventDefault()。这将防止执行默认事件操作。 - Greg
显示剩余3条评论
4个回答

6

来自PhoneGap文档

Opens a URL in a new InAppBrowser instance, the current browser instance, or the system browser.

var ref = window.open(url, target, options);
  • ref: Reference to the InAppBrowser window. (InAppBrowser)
  • url: The URL to load (String). Call encodeURI() on this if the URL contains Unicode characters.
  • target: The target in which to load the URL, an optional parameter that defaults to _self. (String)

    • _self: Opens in the Cordova WebView if the URL is in the white list, otherwise it opens in the InAppBrowser.
    • _blank: Opens in the InAppBrowser.
    • _system: Opens in the system's web browser.

回答你的问题,使用以下方法:

window.open(your_url, '_system', opts);

请注意,域名需要被加入白名单。

2014年4月25日更新:

我认为我对问题有些误解(感谢评论者@peteorpeter)——你想要一种点击InAppBrowser中的链接并在系统浏览器中打开它的方法(例如,在iOS上的Mobile Safari)。这是可能的,但它需要一些预先考虑和应用程序开发人员与页面链接负责人之间的合作。

当你创建一个IAB实例时,你会得到一个引用:

var ref = window.open('http://foo.com', '_blank', {...});

您可以在该引用上注册一些事件侦听器:(点击此处查看详细信息)
ref.addEventListener('loadStart', function(event){ ... });

此事件在IAB的URL更改时触发(例如,点击链接,服务器返回302等...),您可以检查新的URL。
要突破系统浏览器,您需要在URL中定义某种标志。您可以执行任何数量的操作,但是对于此示例,请假设URL中有一个systemBrowser标志: .....html?foo=1&systemBrowser=true 在事件处理程序中查找该标志,并在找到时跳转到系统浏览器。
ref.addEventListener('loadStart', function(event){
    if (event.url.indexOf('systemBrowser') > 0){
        window.open(event.url, '_system', null);
    }
});

请注意,这不是检测URL中标志的最佳方法(可能会导致误报),而且我相信PhoneGap白名单规则仍然适用。

这在链接源于InAppBrowser内部时无法工作,我认为这就是提出的问题(至少在Cordova 3.4.1 / iOS中)。在我的测试中,IAB内的链接始终保持在IAB内,而不管任何“target”值。 - peteorpeter
谢谢提醒。我更新了我的答案,以解释它的工作原理。 - Adam Tuttle
3
'loadstart' 必须全部小写,'loadStart' 不起作用。此外,这不会停止链接在 InAppBrowser 中加载,它仍会在 Safari 中加载。 - Oran Dennison

3

很遗憾,target=_system在InAppBrowser中不起作用。(如果链接来自父级应用程序,则会起作用。)

如果适合您的用例,您可以在IAB中添加事件监听器并嗅探特定的URL模式,就像您在评论中提到的那样。

iab.addEventListener('loadstart', function(event) {
   if (event.url.indexOf("openinSafari") != -1) { 
        window.open(event.url, '_system'); 
    } 
}

这里的“event”不是真正的浏览器事件 - 它是IAB插件的构造 - 不支持event.preventDefault(),因此IAB将加载URL(除了Safari之外)。您可以尝试使用类似以下代码在IAB内部处理该事件:

iab.addEventListener('loadstop', function(event) {
   iab.executeScript('functionThatPreventsOpenInSafariLinksFromGoingAnywhere');  
}

……这是我尚未测试过的。


抱歉,我在更新我的答案之前甚至没有考虑阅读你的答案。我看到我们基本上建议了相同的事情。 :) - Adam Tuttle
别担心 - 有两个位置总比没有好! - peteorpeter

2

这条消息是为了澄清:

如果你通过在loadstart事件中捕获一个链接并使用window.open打开另一个窗口,那么它将会终止你分配给第一个IAB的事件处理程序。

例如:

iab = window.open('http://example.com', '_blank', 'location=no,hardwareback=yes,toolbar=no');
iab.addEventListener('loadstop', function(event) {console.log('stop: ' + event.url);});
iab.addEventListener('loaderror', function(event) { console.log('loaderror: ' + event.message); });
iab.addEventListener('loadstart', function(event) {
    if (event.url.indexOf("twitter") != -1){
        var ref2 = window.open(event.url, '_system', null);

    }
});

当第二个window.open被执行时,它将会删除您之前绑定的所有事件监听器。此外,在执行该window.open后,loadstop事件将不会被触发。
我正在寻找另一种避免这种情况的方法,但目前还没有找到。

非常好。你找到重新绑定事件的解决方案了吗? - Slartibartfast

0

window.open() 在 InAppBrowser 中无法正常工作,无论我是否添加 cordova.js 的脚本引用以获取对 window.open(...'_system') 的支持。因此,我想出了以下解决方案,通过哈希标记将“外部”URL隧道传回到 IAB 主机,以便在那里打开。

在 InAppBrowser 实例内部(我正在使用 AngularJS,但如果您使用 jQuery,则可以将 angular.element 替换为 jQuery$):

angular.element(document).find('a').on('click', function(e) {
    var targetUrl = angular.element(this).attr('href');
    if(targetUrl.indexOf('http') === 0) {
        e.preventDefault();
        window.open('#' + targetUrl);
    }
});

请注意,上述是原生的window.open,而不是cordova.js的window.open。另外,处理程序代码假定所有以http开头的URL应该在外部加载。您可以根据需要更改过滤器,允许一些URL在IAB中加载,其他URL在Safari中加载。
然后,在创建InAppBrowser的父级代码中:
inAppBrowser.addEventListener('loadstart', function(e) {
    if(e.url.indexOf('#') > 0) {
        var tunneledUrl = e.url.substring(e.url.indexOf('#') + 1);
        window.open(tunneledUrl, '_system', null);
    }
});

使用此解决方案,IAB 仍保留在原始页面上,不会触发返回导航箭头的出现,并且 loadstart 处理程序能够在 Safari 中打开请求的 URL。

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