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.