The CommonsBlog

Options for Viewing PDFs

A remarkable number of developers come to Stack Overflow to ask about how to show a PDF… without using a third-party PDF viewer app. The conventional solution for showing PDFs is to use a third-party app, via ACTION_VIEW, as that minimizes work on the developer’s part and gives the user the flexibility to choose what tool to use to view the PDF. But, some developers do not want this.

Frankly, I haven’t quite figured out why they do not want this.

The stated reason, in many cases, is that the developers do not control the PDF viewer app, and therefore do not trust it. However, since the #1 recommended solution is to upload the PDF to a Web site, then use a Google Docs URL to render it in a WebView… how exactly is that an improvement?

Regardless of rationale, there are some in-process options for viewing PDFs, though they have their issues.

The only one native to Android proper is PdfRenderer, and that was only added in Android 5.0, leaving out a lot of current devices at the present time. Also, it seems to have been developed primarily for use with print preview, and specifically with previewing the sorts of PDFs that you might create with WebView or a Canvas. In other words: PdfRenderer chokes on various PDF files, rendering nothing at all. Plus, all it does is give you the ability to convert a page of PDF to a Bitmap, so you still have to roll your own UI around that. It also requires a seekable stream from a ParcelFileDescriptor, which pretty much limits you to rendering files (no assets, no raw resources, etc.).

The PDF renderer that Mozilla uses for Firefox is PDF.js. This works with Android’s WebView, but only the modern incarnation of WebView (i.e., Android 4.4+). It will also add ~2MB to your APK file, in the form of a few MB of JavaScript that you need to package as assets. But, it can handle a fairly wide range of PDF files.

The PDF renderer that Google uses for Chromium is pdfium. However, this is C/C++ code, not JavaScript. Bartosz Schiller’s AndroidPdfViewer library wraps Pdfium in a View that handles rendering and standard gestures (e.g., horizontal swipes to move between pages). This works well on older Android versions (I tested through 4.1), but it adds about 5MB to your APK per CPU architecture. By default, you get six architectures and 30MB of overhead. With careful pruning of unnecessary CPU support (see ya, MIPS) and ABI splits, you can minimize the per-APK footprint, but you wind up with greater deployment complexity.

The next update to my Android book — due out on Monday, if all goes well — has a chapter profiling and demonstrating these options.

I suspect that there are some commercial PDF viewing libraries, which may be worth considering as well.

But, overall, most developers should just let ACTION_VIEW handle the details of letting the user view a PDF.

Find out about new posts on the CommonsBlog via the Atom feed, or follow @CommonsWare on Twitter!