PhoneGap InAppBrowser:打开iOS Safari浏览器

在我们的PhoneGap iOS应用程序中,我们使用InAppBrowser插件来显示一些内容,我们需要在InAppBrowser中打开Safari中的页面。

我们怎样才能在Safari中打开InAppBrowser中的链接?

从phonegap文档 :

在新的InAppBrowser实例,当前浏览器实例或系统浏览器中打开URL。

 var ref = window.open(url, target, options); 
  • ref:引用InAppBrowser窗口。 (InAppBrowser)
  • url:要加载的URL(String)。 如果URL包含Unicode字符,则在此处调用encodeURI()。
  • target:加载URL的目标,默认为_self的可选参数。 (串)

    • _self:如果URL在白名单中,则在Cordova WebView中打开,否则在InAppBrowser中打开。
    • _blank:在InAppBrowser中打开。
    • _system:在系统的Web浏览器中打开。

所以要回答你的问题,请使用:

 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?富= 1&systemBrowser =真

您将在事件处理程序中查找该标志,并在找到时将其踢出系统浏览器:

 ref.addEventListener('loadStart', function(event){ if (event.url.indexOf('systemBrowser') > 0){ window.open(event.url, '_system', null); } }); 

请注意,这不是检测URL中标记的最佳方法(可能导致误报),我很确定PhoneGap白名单规则仍然适用。

不幸的是, 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'); } 

…我没有测试过。

此消息仅供说明:

如果你通过在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事件。

我找到了另一种方法可以避免,但还没有发现..

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都应该从外部加载。 您可以根据需要更改filter,以允许在IAB和Safari中的其他URL中加载某些URL。

然后,在创建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。