by

Titanium – Open PDF with Intents Resolved (Android)

Just over a year ago, Tony Lukasavage wrote a great blog post on the Appcelerator Developer Blog explaining why extra steps were required in Android apps to open PDF files and how to go about it.

Starting about 6 months or so ago, the Appcelerator Q&A began seeing questions regarding this process and the problems users were having.  Now, I haven’t pushed out an app that needed PDF support in nearly 18 months.  Not that PDFs are a bad thing, but none of our clients have required that functionality recently.

So tonight Tim Kimberly asked if I could possibly look into the problem, following an exchange we had earlier in the week on the Q&A.

I copied Tony’s code into an existing project’s app.js. The code performed as expected on an emulator without an SDCard (alert received) and on an emulator with an SDCard but no PDF viewer (alert received).  The code also worked on my Samsung S3, opening the PDF with 3 different viewers.

So now I turned to the Nexus 7, this being the device that Tim Kimberly was testing on.  FAILURE.

Well, with Android development, when in doubt throw in a bunch of Ti.API.info statements and open up DDMS.

From DDMS learned that the line

tmpFile = Ti.Filesystem.createTempFile();

created its file in

file:///data/data/com.test.fff/cache/tifile1080870837tmp.pdf

Problem #1: Ti.Filesystem.createTempFile() may be creating its file in NONE world readable locations.

Fine, the solution then is to create our own filename in the Ti.Filesystem.tempDirectory to be sure.

var filenameBase = new Date().getTime();
tmpFile = Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory,filenameBase+'.pdf');
tmpFile.write(appFile.read());

Excellent! We check to see if tmpFile.exists() is true and it is! Success!
The user now hits the button, fires up an intent and….failure.

Say what? Yeah, file is missing. How can this be? So, throw in some Ti.API.info and learn that from the time we write out the file and check if it exists until the time we hit the button to fire up an intent the file is removed be the system.

11-06 18:44:35.215: I/TiAPI(2451): file written tmpFile exists: true
11-06 18:44:45.385: I/TiAPI(2451): starting intent tmpFile exists: false

Problem #2: The file is being deleted by the system in less than 10 seconds after being written.

Wow! So now what do we do? Eliminate the user delay. Create our temp file immediately before firing up the intent. Move our file system work inside the button event listener. We also change the if statement that was merely checking to see if the variable tmpFile existed to a statement that checks for the actual file’s existence.

button.addEventListener('click', function(e) {
if (Ti.Filesystem.isExternalStoragePresent()) {
var filenameBase = new Date().getTime();
tmpFile = Ti.Filesystem.getFile(Ti.Filesystem.tempDirectory,filenameBase+'.pdf');
tmpFile.write(appFile.read());
if (tmpFile.exists()) {
var intent = Ti.Android.createIntent({
action: Ti.Android.ACTION_VIEW,
type: "application/pdf",
data: tmpFile.nativePath
});
try {
Ti.Android.currentActivity.startActivity(intent);
} catch(e) {
Ti.API.debug(e);
alert('No apps PDF apps installed!');
}
} else {
Ti.API.info('starting intent tmpFile exists: '+tmpFile.exists());
alert('Our file disappeared!');
}
}
});

This code will require some testing against multiple devices to ensure compatibility, but it should get most of you started on the right track.

Work Smart, Code Strong.

Titanium Mobile SDK , build: 3.0.0.v20121030170824
  1. Thanks for this entry. Your article helped me solve the problem I had. Now it’s all working great.
    Regards,
    Marcin

  2. Thanks for posting this. We were having issues with PDF downloads on Galaxy S3 and Galaxy Note devices. This seems to have resolved them.

  3. Hi Stephen,

    Does this code works only when the pdf file is in resources directory?

    I tried using your code to open the downloaded pdf. It opens the Adobe Reader but after that it shows “The Document could not be opened” But when I manually open it from File Manager I can successfully open it in Abode Reader.

  4. Much gratitude to you for sharing this code. I tried many other code fragments that did not work! Once again, I am grateful to you for your generosity of sharing your knowledge and expertise.

Comments are closed.

Webmentions

  • This Week in Titanium Mobile Development: 12 Nov 2012 | TiDev January 3, 2015

    […] Feather resolved the Open PDF with Intents problem for […]

  • This Week in Titanium Mobile Development: 12 Nov 2012 | Titanium Development January 3, 2015

    […] Feather resolved the Open PDF with Intents problem for […]