API Development

Appcelerator PDF Viewer Demo

Viewing a PDF file in a mobile app is a fairly common use case. However, how you do this on Android and iOS are very different. iOS has a built-in document viewer capability, while on Android you open the PDF file in an external application that has support for PDF viewing. This blog post demonstrates both how to view a PDF file downloaded from the web and a PDF file stored as an app resource.

The following links to the Appcelerator online documentation will be useful as background information:

  1. Filesystem Access and Storage
  2. Titanium.UI.iOS.DocumentViewer
  3. Android Intents

iOS

On iOS, the steps are fairly straightfoward.

Application Resource

For the local resource, the steps are:

  1. Get a handle to the file that is stored as a local resource. In this case, the file is stored in /app/assets/pdf/sample.pdf
appFile = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, 'pdf/sample.pdf');
  1. Create an instance of the document viewer with a reference to the PDF file and show the document viewer
var appfilepath = appFile.nativePath
docViewer = Ti.UI.iOS.createDocumentViewer({url:appfilepath});
docViewer.show();
Remote PDF File

For the remote PDF file, the steps are:

  1. Create a file to store the PDF file that will be retrieved from the remote source (e.g. web site). In this case, the PDF is a subway map, so the filename I am creating is map.pdf.
appFile = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'map.pdf');
  1. Retrieve the PDF file using a HTTPClient request. In this case, the PDF file is located at https://www.mbta.com/uploadedfiles/Documents/Schedules_and_Maps/Rapid%20Transit%20w%20Key%20Bus.pdf
var appfilepath = appFile.nativePath;
var xhr = Ti.Network.createHTTPClient();
xhr.onload = function() {
    appFile.write(this.responseData);
  docViewer = Ti.UI.iOS.createDocumentViewer({url:appfilepath});
  docViewer.show();
};
xhr.onerror = function() {
    alert("Cannot retrieve PDF from web site")
};
xhr.timeout = 10000;
xhr.open("GET", "https://www.mbta.com/uploadedfiles/Documents/Schedules_and_Maps/Rapid%20Transit%20w%20Key%20Bus.pdf");
xhr.send();

Android

On Android, there are a few more steps involved because:

  1. An Intent must be created to look for an application on the device that can handle PDF files and then pass the PDF file on to the app
  2. In order to pass the PDF file to an external PDF viewer application, the PDF file must be in external memory (i.e. SDCard)

But, Appcelerator makes this all easy.

Application Resource

For the local resource, the steps are:

  1. Get a handle to the file that is stored as a local resource. In this case, the file is stored in /app/assets/pdf/sample.pdf and store it in external memory.
var originalFile = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, 'pdf/sample.pdf');
appFile = Ti.Filesystem.getFile(Ti.Filesystem.externalStorageDirectory, 'sample.pdf');
appFile.write(originalFile.read());
  1. Try to open an external PDF viewer application and pass the PDF File
var appfilepath = appFile.nativePath;
try{
    Ti.Android.currentActivity.startActivity(Ti.Android.createIntent({
        action: Ti.Android.ACTION_VIEW,
        type: 'application/pdf',
        data: appfilepath
    }));
} catch(e) {
    Ti.API.info('error trying to launch activity, e = '+e);
    alert('No PDF apps installed!');
}
Remote PDF File

For the remote PDF file, the steps are:

  1. Create a file to store the PDF file that will be retrieved from the remote source (e.g. web site). In this case, the PDF is a subway map, so the filename I am creating is map.pdf.
appFile = Ti.Filesystem.getFile(Ti.Filesystem.externalStorageDirectory, 'map.pdf');
  1. Retrieve the PDF file using a HTTPClient request. In this case, the PDF file is located at https://www.mbta.com/uploadedfiles/Documents/Schedules_and_Maps/Rapid%20Transit%20w%20Key%20Bus.pdf and launch the intent:
var appfilepath = appFile.nativePath;
var xhr = Ti.Network.createHTTPClient();
xhr.onload = function() {
    appFile.write(this.responseData);
  try{
    Ti.Android.currentActivity.startActivity(Ti.Android.createIntent({
        action: Ti.Android.ACTION_VIEW,
        type: 'application/pdf',
        data: appfilepath
    }));
  } catch(e) {
    Ti.API.info('error trying to launch activity, e = '+e);
    alert('No PDF apps installed!');
  }
};
xhr.onerror = function() {
    alert("Cannot retrieve PDF from web site")
};
xhr.timeout = 10000;
xhr.open("GET", "https://www.mbta.com/uploadedfiles/Documents/Schedules_and_Maps/Rapid%20Transit%20w%20Key%20Bus.pdf");
xhr.send();

Putting It All Together

A sample app that handles iOS and Android and provides more modular, reusable code can be found here.

Screen Shots

iPhone Screen Shots:

Appcelerator PDF Viewer iPhone screenshot example

Android Screen Shots:

Appcelerator PDF Viewer Android screenshot example