Viewing local PDFs in Ionic on browser, iOS and Android 5 +

This is a provider that allows viewing of local PDFs on iOS and Android. Tested on Android 5,6 and 7. Tested on Ionic 3.19.1.

This will never work on Android if you use live reload as the above version of Ionic doesn’t see cordova. It does work without the live reload flag. So this, won’t show the PDF:

ionic run android -l

It uses Ionic Native File, Document Viewer and In App Browser. Ionic Native File Opener doesn’t work on iOS 11 at the moment so that isn’t an option and this solution uses the Document Viewer plugin on iOS but uses In App Browser on Android. Document Viewer on Android requires a third party app install which feels clunky and I wanted to avoid. This solution uses whatever native PDF viewer is available on Android (i.e. Google Docs).

First you need to add a line to your Ionic project config.xml to bypass the new permissions on Android 7 that prevent the local files from being viewed. There will no doubt be a more elegant solution but I wanted a quick fix:

<preferencename="android-targetSdkVersion"value="23" />
This changes the default Android target version in the androidmanifest.xml file that Ionic creates during the build process from 26 to 23.
Create a new provider using the Ionic CLI:
ionic g provider PdfViewer
Follow the installation instruction on the Ionic Native File, In App Browser and Document Viewer plugin pages. Add all three, and your new provider (if the CLI didn’t do it already) to your app’s module (app.module.ts):
import { File } from '@ionic-native/file';
import { DocumentViewer } from '@ionic-native/document-viewer';
import { InAppBrowser } from '@ionic-native/in-app-browser';
import { PdfViewerProvider } from '../providers/pdf-viewer/pdf-viewer';
And update your providers:
providers: [
  StatusBar,
  SplashScreen,
  File,
  DocumentViewer,
  InAppBrowser,
  {provide: ErrorHandler, useClass: IonicErrorHandler},
  PdfViewerProvider
]
Copy and paste this into your new provider pdf-viewer.ts
import { Injectable } from '@angular/core';
import { normalizeURL, Platform } from 'ionic-angular';
import { File } from '@ionic-native/file';
import { DocumentViewer } from '@ionic-native/document-viewer';
import { InAppBrowser } from '@ionic-native/in-app-browser';

/*
****************************
This requires adding the line
<preference name="android-targetSdkVersion" value="23" />
to the project config.xml otherwse Android 7 permissions don't allow opening the PDF file
****************************
We're going to use Platfrom for platffrom detection then:
Document Viewer for iOS
In App Browser for Android
window.open for browser
And finally normalizeURL to propwerly format the URL based on platfrom.
*/

@Injectable()
export class PdfViewerProvider {
constructor(privatedocument:DocumentViewer, privateiab:InAppBrowser, privatefile:File, publicplt:Platform) {
//console.log('Hello PdfViewerProvider Provider');
}

openDocument(fileName) {
letassetDirectory='assets/files/';
console.log(this.plt);
console.log(assetDirectory);
// normal link for browser
if ( !this.plt.is('cordova') &&!this.plt.is('android') ) {
console.log('browser');
window.open(assetDirectory+fileName);
return;
}

// iOS and Android native
letfilePath=this.file.applicationDirectory+'www/'+assetDirectory;
// android using in app browser which prompts native file opener
if (this.plt.is('android')) {
lettheMove=this.file.copyFile(filePath, fileName, this.file.externalDataDirectory, fileName);
filePath=this.file.externalDataDirectory;
console.log(filePath+fileName);
constbrowser=this.iab.create(normalizeURL(filePath+fileName), '_system', 'location=yes');
console.log(browser);
}

// ios use ionic document viewer becasue it's a nicer ux
elseif (this.plt.is('ios')) {
constoptions= {
title:'My PDF',
documentView : {
closeLabel :'DONE'
},

navigationView : {
closeLabel :'DONE'
},
email : {
enabled :true
},
print : {
enabled :false
},
openWith : {
enabled :true
},
bookmarks : {
enabled :false
},
search : {
enabled :false
},
autoClose: {
onPause :true
}
}
console.log(filePath+fileName);
constviewer=this.document.viewDocument(filePath+fileName, 'application/pdf', options);
console.log(viewer);
}
}
}

Import your provider into whatever page component you want to display your PDF from:

import { PdfViewerProvider } from '../../providers/pdf-viewer/pdf-viewer';

and inject it into your constructor:

constructor(publicnavCtrl:NavController, publicnavParams:NavParams, publicpdfViewer:PdfViewerProvider) {}

and, after your constructor, add a function to call the function from your provider:

openDocument(fileName) {

this.pdfViewer.openDocument(fileName);

}
And in your html file
<button ion-button secondary (click)="openDocument('yourfile.pdf')">Open PDF</button>

5 comments

  1. Thanks for the pointers – this approach worked great for me after trying in vain with the various cordova plugins available!

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.