在我的离子(v1.2.4)应用程序中,有一个嵌入式youtube播放器,其中有一个链接"在youtube上观看"。如果用户点击此链接,则会在cordova的网络视图中打开youtube网站。它破坏了我的应用程序的当前状态。我想在系统的网络浏览器(应用程序浏览器插件中的cordova)中打开该链接。
与任何iframe中的任何链接相同(vimeo,soundcloud ...)
此链接无法在iframe外部使用JS进行修改,因为跨域安全问题。因此,我无法将目标属性从_blank
更新为_system
。
显示对话框onbeforeunload
实际上不是一个选项,因为它看起来很难看:)
是否有可能避免将页面加载到同一webview或系统的Web浏览器中?
使用iframe sandbox
属性打破链接不是一种选择,因为它会完全打破youtube播放器。
谢谢和欢呼
ps:我问了这个问题here,但无法获得任何有用的信息
答案 0 :(得分:3)
感谢thepio提供allow-intent
和allow-navigation
的提示。我第一次真正深入研究cordova-whitelist-plugin
。最后我通过在config.xml
allow
属性来修复我在android上的问题
<!-- Allow links to web pages to open in a browser -->
<allow-intent href="http://*/*" />
<allow-intent href="https://*/*" />
对于Android没有allow-navigation
。完美的白标解决方案。无法在iOS上找到如何执行此操作,因为iOS需要allow-navigation
属性才能加载iframe内容。
要以肮脏的方式解决我在iOS上的问题,我将其添加到我的config.xml:
<platform name="ios">
<allow-navigation href="https://w.soundcloud.com/player/*"/>
<allow-navigation href="https://www.youtube.com/embed/*"/>
<allow-navigation href="https://player.vimeo.com/video/*"/>
</platform>
现在只加载了iframe内容。幸运的是,iframe内的每个链接(在YouTube上观看,分享,比如vimeo ......)都指向另一个域/子域,因此它在iOS上被阻止。
如果有任何建议,如何为iOS创建白标解决方案,我很满意。
由于
答案 1 :(得分:1)
好的,这是一种硬核解决方案,应该重新编写/编码。此解决方案使用cordova挂钩,并在从a-tag中单击时,将http或https协议的 ALL 链接打开到本机Web浏览器。例如<a href="https://www.youtube.com/embed">
。这不仅会影响iframe,还会影响所有链接。
请注意,因为这可能会影响您应用中的某些不需要的链接。
我正在运行
首先,您需要在hooks / after_platform_add文件夹中创建一个钩子。只有在您使用ionic platform add <platform>
或cordova platform add <platform>
时才会运行此挂钩。如果您没有名为after_platform_add的文件夹,只需创建一个。然后创建一个文件“01_ios_external_links_hook.js”。
另请阅读Cordova hooks文档:
https://cordova.apache.org/docs/en/latest/guide/appdev/hooks/
有几种方法可以定义钩子并为它们创建文件夹似乎已被弃用,因此您应该使用config.xml来附加钩子。
您可以调用您的文件,如果您正在使用文件夹,请记住添加文件的访问权限。通常在终端:
chmod +x project/hooks/after_platform_add/01_ios_external_links_hook.js.
请注意,此修复程序仅适用于iOS设备,因为在Android上,您可以通过设置<allow-intent href="http://*/*" />
和设置<access origin="*" />
来解决此问题。但是在最新的Cordova-ios和白名单插件上,您需要设置<allow-navigation href="*.youtube.com" />
或类似内容以允许在iOS上加载iframe的内容。这将导致您描述的情况是iframe中的外部网址将在网页视图中打开。
但回到解决方案。这是我在01_ios_external_links.js文件中的代码:
#!/usr/bin/env node
var fs = require('fs');
var replace = require('replace');
if (fs.existsSync('platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.m')) {
console.log('platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.m - FOUND: fixing');
replace({
regex: /.*BOOL shouldLoad = YES;*./g,
replacement: 'BOOL shouldLoad = YES; NSURL * requesturl = [request URL]; NSString * url = [[request URL]absoluteString]; NSString * documenturl = [[request mainDocumentURL]absoluteString]; if ((navigationType == UIWebViewNavigationTypeLinkClicked && ([[requesturl scheme] isEqualToString:@"http"] || [[requesturl scheme] isEqualToString:@"https"])) || (([url isEqualToString:documenturl]) && ([[requesturl scheme] isEqualToString:@"http"] || [[requesturl scheme] isEqualToString:@"https"]))) { [[UIApplication sharedApplication] openURL:requesturl]; return NO;}',
paths: ['platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.m'],
recursive: true,
silent: true,
});
} else {
console.log('platforms/ios/CordovaLib/Classes/Private/Plugins/CDVUIWebViewEngine/CDVUIWebViewDelegate.m - NOT FOUND');
}
请注意,这是一项有风险的操作,但我当时没有办法解决这个问题。上面的代码搜索在给定的路径中是否有一个名为CDVUIWebViewDelegate.m的文件,然后尝试在那里找到一段代码并用另一段代码替换它。但简而言之,上面的代码将在CDVUIWebViewDelegate中修改iOS的平台特定代码,并在此文件中添加以下类型的if语句:
NSURL * requesturl = [request URL];
NSString * url = [[request URL]absoluteString]; // URL that was requested
NSString * documenturl = [[request mainDocumentURL]absoluteString]; // Main document URL
if ((navigationType == UIWebViewNavigationTypeLinkClicked && ([[requesturl scheme] isEqualToString:@"http"] || [[requesturl scheme] isEqualToString:@"https"])) || (([url isEqualToString:documenturl]) && ([[requesturl scheme] isEqualToString:@"http"] || [[requesturl scheme] isEqualToString:@"https"]))) {
[[UIApplication sharedApplication] openURL:requesturl]; // forward to application router
return NO;
}
考虑到我不是一个客观的编码器,这对我自己也是新的,我做了这个解决方案,因为我没有找到任何其他解决方案来解决我的问题。上述if语句可以而且应该根据您的需要进行修改。我只在开发环境中使用了此代码,并且需要进一步调查并改进此方法,然后再将其应用到生产环境中。
请记住,您需要删除并添加平台才能生效。这仅在添加如上所述的平台时发生。
但就是这样。现在,您的iOS应用程序将打开本机浏览器中的所有URL。希望这有助于您找到(更好?)解决此问题的正确方向。
答案 2 :(得分:0)
我也面临同样的问题,并且能够使用以下代码解决。
$('iframe#youtube').get(0).contentWindow.open = function (url) {
cordova.InAppBrowser.open(url, "_system");
};
此代码仅适用于iOS。