【问题标题】:Ionic: External link in iframe opens in webview (embed youtube player)Ionic:iframe 中的外部链接在 web 视图中打开(嵌入 youtube 播放器)
【发布时间】:2016-08-07 08:37:59
【问题描述】:

在我的 ionic (v1.2.4) 应用程序中,有一个嵌入式 youtube 播放器,带有“在 youtube 上观看”链接。如果用户单击此链接,则 youtube 网站将在 cordova 的 web 视图中打开。它破坏了我的应用程序的当前状态。我想在系统的网络浏览器中打开该链接(应用浏览器插件中的cordova)。

与任何 iframe(vimeo、soundcloud...)中的任何链接相同

由于跨域安全问题,无法使用 iframe 外部的 JS 修改此链接。所以我无法将目标属性从_blank 更新为_system

显示对话框onbeforeunload 不是一个真正的选项,因为它看起来很丑:)

是否有可能避免将页面加载到同一个 webview 或系统的 web 浏览器中? 使用 iframe 的 sandbox 属性断开链接不是一种选择,因为它完全破坏了 youtube 播放器。

感谢和欢呼

ps:我问了这个问题here,但没有得到任何有用的信息

【问题讨论】:

    标签: iframe ionic-framework youtube-iframe-api


    【解决方案1】:

    感谢 thepio 提供 allow-intentallow-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 创建一个白标解决方案,我全神贯注。

    谢谢

    【讨论】:

      【解决方案2】:

      好的,这是一种硬核解决方案,可能应该重新编写/编码。此解决方案使用cordova 钩子,并在从a 标记单击它们时将具有http 或https 协议的ALL 链接打开到本机Web 浏览器。例如&lt;a href="https://www.youtube.com/embed"&gt;。这不仅会影响 iframe,还会影响所有链接。

      请小心,因为这可能会影响您应用中的一些不需要的链接

      我在跑步

      • 科尔多瓦 6.1.1
      • Cordova-ios 4.1.1
      • Cordova-android 5.1.1

      首先,您需要在 hooks/after_platform_add 文件夹中创建一个挂钩。仅当您使用 ionic platform add &lt;platform&gt;cordova platform add &lt;platform&gt; 时才会运行挂钩。如果您没有名为 after_platform_add 的文件夹,只需创建一个。然后创建一个文件“01_ios_external_links_hook.js”。

      另外请阅读 Cordova hooks 文档:

      https://cordova.apache.org/docs/en/latest/guide/appdev/hooks/

      似乎不推荐使用多种方法来定义挂钩并为其创建文件夹,因此您应该使用 config.xml 来附加挂钩。

      https://cordova.apache.org/docs/en/latest/guide/appdev/hooks/index.html#via-hooks-directory-deprecated

      您可以对文件进行任何调用,如果您使用文件夹进行调用,请记住为文件添加访问权限。通常在终端:

      chmod +x project/hooks/after_platform_add/01_ios_external_links_hook.js.
      

      请注意,此修复仅适用于 iOS 设备,因为在 android 上您可以通过设置 &lt;allow-intent href="http://*/*" /&gt; 和设置 &lt;access origin="*" /&gt; 来处理此问题。但在最新的 Cordova-ios 和 whitelist-plugin 上,您需要设置 &lt;allow-navigation href="*.youtube.com" /&gt; 或类似的设置以允许 iframe 的内容在 iOS 上加载。这将导致您描述的情况,即来自 iframe 的外部 url 将在 webview 中打开。

      但回到解决方案。这是我在 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;
      }
      

      考虑到我不是 Objective-c 编码器,这对我自己来说也是全新的,我提出了这个解决方案,因为我没有找到任何其他有效的解决方案来解决我的问题。上面的 if 语句可以而且应该根据您的需要进行修改。我只在开发环境中使用过此代码,需要进一步调查并改进此方法,然后才能将其实施到生产环境中。

      请记住,您需要删除并添加平台才能使其生效。这只发生在如上所述添加平台时。

      但就是这样。现在您的 iOS 应用程序将在本机浏览器中打开所有 url。希望这可以帮助您找到(更好?)解决此问题的正确方向。

      【讨论】:

        【解决方案3】:

        我也遇到了同样的问题,用下面的代码解决了。

        $('iframe#youtube').get(0).contentWindow.open = function (url) {
            cordova.InAppBrowser.open(url, "_system");
        };
        

        此代码仅适用于 iOS。

        【讨论】:

        • 我所做的是在构造函数中初始化 InAppBrowser 对象,并创建了一个函数来使用 '_system' 打开 url
        猜你喜欢
        • 1970-01-01
        • 2012-07-26
        • 1970-01-01
        • 2016-09-19
        • 1970-01-01
        • 2020-09-07
        • 2012-07-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多