Ionic:使用 cordova-plugin-inappbrowser 拦截 PDF URL

Ionic: Intercept PDF URLs with cordova-plugin-inappbrowser

我正在使用 ionic 3 构建一个 Android/iOS 应用程序,它仅由 cordova-plugin-inappbrowser(版本 3.0.0)的 webview 和响应式主页组成。主页包含指向网站和(在线)PDF 文件的不同链接。

据我了解,Android 中的 webview(我还没有尝试 iOS)不支持打开 PDF 文件。 这就是为什么我想拦截被调用的 URLs,并以其他方式打开它们,如果它们以 '.pdf' 结尾:

import { Component } from '@angular/core';
import {InAppBrowser, InAppBrowserObject, InAppBrowserOptions} from "@ionic-native/in-app-browser";

export class HomePage {

  options : InAppBrowserOptions = {
    location : 'no',//Or 'no'
    hidden : 'no', //Or  'yes'
    clearcache : 'yes',
    clearsessioncache : 'yes',
    zoom : 'no',//Android only ,shows browser zoom controls
    hardwareback : 'yes',
    mediaPlaybackRequiresUserAction : 'no',
    shouldPauseOnSuspend : 'no', //Android only
    closebuttoncaption : 'Close', //iOS only
    disallowoverscroll : 'no', //iOS only
    toolbar : 'no', //iOS only
    enableViewportScale : 'no', //iOS only
    allowInlineMediaPlayback : 'no',//iOS only
    presentationstyle : 'pagesheet',//iOS only
    fullscreen : 'yes'//Windows only
  };

  constructor(private inAppBrowser: InAppBrowser) {
    this.openWithCordovaBrowser('http://url.tohomepage.com');
  }

  public openWithCordovaBrowser(url : string){
    let target = "_self";
    this.browser = this.inAppBrowser.create(url,target,this.options);
    this.browser.on('loadstart').subscribe((event) => {
      if(event.url.endsWith('.pdf'))
      {
        //Open PDF in some other way
      }
    });
    this.browser.on('loadstop').subscribe((event) => {
    });
    this.browser.on('exit').subscribe((event) => {
    });
  }
}

我现在的问题是,当调用 PDF-URL 时,会触发 3 个事件(loadstart、loadstop、loaderror)中的 none。通常 URL 这些事件会按预期触发。 有没有其他方法可以拦截这些电话? (据我所知这个版本不存在beforeload事件)

感谢任何help/hints!


编辑:

我按照建议直接从 github master 安装了 cordova-plugin-inappbrowser。 据我所知,'beforeload' 通道已在模块中实现。 但是 'beforeload' 事件仍然没有触发。 ('loadstart' 但是适用于 none-PDF URLs)。

declare var cordova: any;
...

constructor() {
    var iabRef = cordova.InAppBrowser.open("http://someurl.com", "_blank", "beforeload=yes");

    iabRef.addEventListener('beforeload', function(params, callback){
      alert('Beforeload fired');

      // If the URL being loaded is a PDF
      if(params.url.match(".pdf")){
        // Open PDFs in system browser (instead of InAppBrowser)
        cordova.inAppBrowser.open(params.url, "_system");
      }else{
        // Invoke callback to load this URL in InAppBrowser
        callback(params.url);
      }
    });

    iabRef.addEventListener('loadstart', function(params, callback){
      alert('Loadstart fired');
    });
}

如果您直接从添加 beforeload 事件的 Github master branch, there's an unreleased feature added by PR #276 安装 cordova-plugin-inappbrowser

首先直接从master安装插件:

cordova plugin add https://github.com/apache/cordova-plugin-inappbrowser

然后像这样使用它:

// Open InAppBrowser on initial page
var iabRef = cordova.InAppBrowser.open("http://www.someurl.com", "_blank", "beforeload=yes");

// Add beforeload event handler which is called before each new URL is loaded into the InAppBrowser Webview
iabRef.addEventListener('beforeload', function(params, callback){
    // If the URL being loaded is a PDF
    if(params.url.match(".pdf")){
        // Open PDFs in system browser (instead of InAppBrowser)
        cordova.InAppBrowser.open(params.url, "_system");
    }else{
        // Invoke callback to load this URL in InAppBrowser
        callback(params.url);
    }
});

所以最后通过一些变通办法我让它工作了:

declare var cordova: any;

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  private iabRef;

  constructor(private inAppBrowser: InAppBrowser, private platform: Platform, private spinnerDialog: SpinnerDialog, private file: File, private fileTransfer: FileTransfer, private fileOpener: FileOpener) {

    this.platform.ready().then(() => {
      if (this.platform.is('android')) {
        this.androidBrowser();
      } else {
        this.iosBrowser();
      }
    });
  }

  iosBrowser() {
    let browser = this.inAppBrowser.create("http://someurl.com", "_blank", "location=no,navigationbuttoncolor=#ffffff);
  }

  androidBrowser() {
    let that = this;

    this.iabRef = cordova.InAppBrowser.open("http://someurl.com", "_blank", "beforeload=yes,location=no");

    this.iabRef.addEventListener('beforeload', function(params, callback){
      // If the URL being loaded is a PDF
      if(params.url.match(".pdf")){
        that.openPDF(params.url);
      } else {
        callback(params.url);
      }
    }, false);

    this.iabRef.addEventListener('loadstart', function(params, callback){
      that.spinnerDialog.show(null, null, true);
    });

    this.iabRef.addEventListener('loadstop', function(params, callback){
      that.spinnerDialog.hide();
    });

    this.iabRef.addEventListener('exit', function(params, callback){
      that.platform.exitApp();
    });
  }

  openPDF(url: string) {
    let title = url.substring(
      url.lastIndexOf("/") + 1,
      url.lastIndexOf(".pdf")
    );

    let path =  this.file.dataDirectory;

    const transfer = this.fileTransfer.create();
    transfer.download(url, path + title + '.pdf').then(entry => {
      let url = entry.toURL();
      this.fileOpener.open(url, 'application/pdf');
    });
  }
}

直接从 GitHub 存储库安装 Cordova 插件后,'beforeload' 事件被触发(虽然有时只有在第二次点击 pdf link 之后,但我将不得不忍受现在)。 起初我试图用另一个 cordova.InAppBrowser.open("http://someurl.com/pdffile.pdf", "_system"); 打开 PDF-URL 这很有效,但是,当我 return 进入我原来的 inAppBrowser 时,网站就卡住了。按钮和 links 显示他们被点击的反馈,但浏览器没有反应了。由于我无法解决该问题,我现在正在下载 pdf 文件并使用 FileOpener 插件打开它。当我现在 return 从 pdf 转到应用程序时,浏览器仍然像以前一样工作。

对于 iOS 我无法获得它 运行 与 android 一样的直接 Cordova 插件。所以如果设备是 运行 iOS,我用 ionic native inAppBrowser 插件打开它。 iOS Webview 可以很好地处理 pdf,尽管无法下载显示的 pdf,对此我还找不到解决方案。