Unlock the Power of Direct PDF Editing with WebViewer 10.7

How to Build an Android PDF Viewer Using Java

By Branden Fung | 2018 Nov 21

Sanity Image
Read time

4 min

In order to let users view PDF documents in an Android app, it's common practice to defer this functionality to a third-party app on the user’s device. By doing so, developers won't have to build their own PDF viewer from scratch. However, this isn't always the best solution. What if you want to view PDF documents directly in your app? Luckily, the Android SDK provides classes to handle PDF documents in apps running Android 5.0 or higher.

In this blog post, we’ll use PdfRenderer from the android.graphics.pdf package to create a basic PDF viewer in your Android app. Then, we'll see how easy it is to implement a document viewer using the Apryse SDK. Here are a few steps to get you started.

For reference, the sample code for this post can be found at Github.

View a PDF Using the Android SDK

Copied to clipboard

To keep things simple, we're going to view a PDF file stored in the raw resource folder (i.e. res/raw/sample.pdf). Your app will also need to set the minimum API level to 21 (Android 5.0).

    // ...
    private PdfRenderer mPdfRenderer;
    private PdfRenderer.Page mPdfPage;
    private ImageView mImageView;
    
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mPdfPage != null) {
            mPdfPage.close();
        }
        if (mPdfRenderer != null) {
            mPdfRenderer.close();
        }
    }
    

Add PdfRenderer and PdfRenderer.Page member variables to your activity so that we can clean them up later. You'll also need to add an ImageView to your activity in order to display the PDF:

    // Copies the resource PDF file locally so that PdfRenderer can handle the file
    void copyToLocalCache(File outputFile, @RawRes int pdfResource) throws IOException {
        if (!outputFile.exists()) {
            InputStream input = getResources().openRawResource(pdfResource);
            FileOutputStream output;
            output = new FileOutputStream(outputFile);
            byte[] buffer = new byte[1024];
            int size;
            // Just copy the entire contents of the file
            while ((size = input.read(buffer)) != -1) {
                output.write(buffer, 0, size);
            }
            input.close();
            output.close();
        }
    }
    

In order for PdfRenderer to handle PDFs from the res/raw folder, we'll need to copy the file and cache it locally. Add this method to your activity:

    // Display a page from the PDF on an ImageView
    void openPdfWithAndroidSDK(ImageView imageView, int pageNumber) throws IOException {
        // Copy sample.pdf from 'res/raw' folder into local cache so PdfRenderer can handle it
        File fileCopy = new File(getCacheDir(), FILE_NAME);
        copyToLocalCache(fileCopy, R.raw.sample);

        // We will get a page from the PDF file by calling openPage
        ParcelFileDescriptor fileDescriptor =
                ParcelFileDescriptor.open(fileCopy,
                        ParcelFileDescriptor.MODE_READ_ONLY);
        mPdfRenderer = new PdfRenderer(fileDescriptor);
        mPdfPage = mPdfRenderer.openPage(pageNumber);

        // Create a new bitmap and render the page contents on to it
        Bitmap bitmap = Bitmap.createBitmap(mPdfPage.getWidth(),
                mPdfPage.getHeight(),
                Bitmap.Config.ARGB_8888);
        mPdfPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);

        // Set the bitmap in the ImageView so we can view it
        imageView.setImageBitmap(bitmap);
    }
    

Then you can display a page from your PDF by loading it to an ImageView as a bitmap:

PDFRenderer Viewer

As you can see, using PdfRenderer is an easy way to create a simple single-page PDF viewer in your Android app. However, if you need users to interact with a PDF document, then I'm afraid you're out of luck. The Android SDK does not provide basic UI controls for PDF viewing like page zooming and scrolling, and PdfRenderer only supports opening one page at a time - you'll need to write your own UI to handle user interaction and multi-page documents.

Additionally, PdfRenderer does not support password-protected or encrypted files, and uses PDFium for rendering which only works well with simple documents. You could run in to some rendering inconsistencies or failures when working with more complex or unsupported PDF documents. For a more stable and interactive viewing experience, you'll have to look elsewhere for a solution.

Fortunately, Apryse's Android PDF SDK comes with a fully-featured document viewer that includes these basic controls in addition to features such as:

Also, it's easy as pie to integrate with your Android app. Here's how!

View a PDF Using Apryse

Copied to clipboard

We'll be using DocumentActivity as our PDF viewer. Set up this activity as described in this short guide.

    // Open the document 'res/raw/sample.pdf' in DocumentActivity
    DocumentActivity.openDocument(this, R.raw.sample);
    

From your main activity, open the PDF document in DocumentActivity by calling:

That's it! You now have a fully-featured document viewer in your Android app.

Apryse Viewer

Out of the box, Apryse provides an interactive document viewer that can be easily integrated into existing Android apps with dozens of features, giving users a better document viewing experience. What's even better is that it's highly customizable, allowing for feature customization and UI theming to fit all use cases. Additionally, Apryse also offers comprehensive solutions for both mobile, server and web based applications. Interested in learning more about our WebViewer? Check out our latest guide here.

To get started, just download our [free trial}(/documentation/android/get-started/) and explore our guides & documentation for our Android PDF library.

If you have any questions about Apryse's Android PDF SDK, feel free to get in touch!

You can find the source code for this blog post at Github.

Sanity Image

Branden Fung

Share this post

email
linkedIn
twitter