3

I know this question has been asked many times but it's still unclear for me if there is an existing and properly working library to natively display PDF documents.

I only want to view a PDF document which is stored inside my app. Opening a new Activity is ok for me, I don't need to display it inside an existing view. I've already built a piece of code to launch an activity intent for reading my local PDF file, but of course, if no PDF Viewer app is already installed on the device, then nothing happens.

I've heard about APV, VuDroid, droidreader, etc but it seems that they all are APKs, not libraries that can be used inside my app code.

So, is there any real Android library to achieve this?

Thanks in advance.

thomaus
  • 6,170
  • 8
  • 45
  • 63
  • Please check my answer and if u have any problem then tell me. – Dipak Keshariya Jun 28 '12 at 11:45
  • Please see below my SO answer's link for read pdf from sdcard and add PDFViewer.jar file into your application's java build path. [Read PDF Using PDFViewer](http://stackoverflow.com/questions/11152956/example-of-code-to-implement-a-pdf-reader/11153601#11153601) – Dipak Keshariya Jun 28 '12 at 11:12
  • I don't get it. Where is the library available? – thomaus Jul 03 '12 at 13:33
  • download pdfviewer.jar from this link. http://www.ziddu.com/download/19248664/PdfViewer.jar.html – Dipak Keshariya Jul 04 '12 at 04:23
  • But is there any documentation for your library? I don't even know how to use it... – thomaus Jul 12 '12 at 07:03
  • first download library from above link and after that add this library into your application's java build path and after that use above SO link's code. – Dipak Keshariya Jul 12 '12 at 07:26
  • All right, I did so and it's almost working. The only thing I don't know how to do is setting the path of a local PDF file, I mean, a PDF file included in the "raw" or the "assets" folder of the app. Do you know how to do that? – thomaus Jul 17 '12 at 18:15
  • I tried to copy the PDF file on the device SD card and call `String SD_CARD_PATH = Environment.getExternalStorageDirectory().getAbsolutePath().toString(); intent.putExtra(PdfViewerActivity.EXTRA_PDFFILENAME, SD_CARD_PATH + "/test.pdf");` but still I get the ST='file '/mnt/sdcard/test.pdf' not found'. Any clue? – thomaus Jul 18 '12 at 17:12
  • After insert pdf into your device sdcard root your device or scan media files and then try it. – Dipak Keshariya Jul 19 '12 at 04:28
  • I means after the copy of pdf file switch off your device and again switch on your device and then check. – Dipak Keshariya Jul 19 '12 at 08:30
  • So it seems that /mnt/extSdCard/test.pdf works while Environment.getExternalStorageDirectory().toString() + "/test.pdf" doesn't. Why??? – thomaus Jul 19 '12 at 08:58
  • first copy pdf file into your sdcard from your computer and then root your device. – Dipak Keshariya Jul 19 '12 at 09:07
  • I did so already. The problem is that the library doesn't accept `Environment.getExternalStorageDirectory().toString()` as a correct path, and I think it should. Otherwise, how is it possible to make it work? – thomaus Jul 19 '12 at 09:10
  • I think this is best : https://github.com/barteksc/AndroidPdfViewer/ – Pratik Butani Aug 24 '18 at 05:36

3 Answers3

2

This one you can try it which works in offline mode https://github.com/bitfield66/PdfViewerAndroid_Offline

which just accepts pdf path.

0

Firstly to view a pdf in android you have to convert the pdf into images then display them to the user. (i am going to use a webview)

So to do this we need this library. It is my edited version of this git.

After you have imported the library into your project you need to create your activity.

The XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView
            android:id="@+id/webView1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>

</LinearLayout>

The java onCreate:

//Imports:
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.view.ViewTreeObserver;
import android.webkit.WebView;
import com.sun.pdfview.PDFFile;
import com.sun.pdfview.PDFImage;
import com.sun.pdfview.PDFPage;
import com.sun.pdfview.PDFPaint;
import net.sf.andpdf.nio.ByteBuffer;
import net.sf.andpdf.refs.HardReference;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;

//Globals:
private WebView wv;
private int ViewSize = 0;

//OnCreate Method:
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //Settings
    PDFImage.sShowImages = true; // show images
    PDFPaint.s_doAntiAlias = true; // make text smooth
    HardReference.sKeepCaches = true; // save images in cache

    //Setup webview
    wv = (WebView)findViewById(R.id.webView1);
    wv.getSettings().setBuiltInZoomControls(true);//show zoom buttons
    wv.getSettings().setSupportZoom(true);//allow zoom
    //get the width of the webview
    wv.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
    {
        @Override
        public void onGlobalLayout()
        {
            ViewSize = wv.getWidth();
            wv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        }
    });

    pdfLoadImages();//load images
}

Load Images:

private void pdfLoadImages()
{
    try
    {
        // run async
        new AsyncTask<Void, Void, Void>()
                {
                    // create and show a progress dialog
                    ProgressDialog progressDialog = ProgressDialog.show(MainActivity.this, "", "Opening...");

                    @Override
                    protected void onPostExecute(Void result)
                    {
                        //after async close progress dialog
                        progressDialog.dismiss();
                    }

                    @Override
                    protected Void doInBackground(Void... params)
                    {
                        try
                        {
                            // select a document and get bytes
                            File file = new File(Environment.getExternalStorageDirectory().getPath()+"/randompdf.pdf");
                            RandomAccessFile raf = new RandomAccessFile(file, "r");
                            FileChannel channel = raf.getChannel();
                            ByteBuffer bb = ByteBuffer.NEW(channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()));
                            raf.close();
                            // create a pdf doc
                            PDFFile pdf = new PDFFile(bb);
                            //Get the first page from the pdf doc
                            PDFPage PDFpage = pdf.getPage(1, true);
                            //create a scaling value according to the WebView Width
                            final float scale = ViewSize / PDFpage.getWidth() * 0.95f;
                            //convert the page into a bitmap with a scaling value
                            Bitmap page = PDFpage.getImage((int)(PDFpage.getWidth() * scale), (int)(PDFpage.getHeight() * scale), null, true, true);
                            //save the bitmap to a byte array
                            ByteArrayOutputStream stream = new ByteArrayOutputStream();
                            page.compress(Bitmap.CompressFormat.PNG, 100, stream);
                            stream.close();
                            byte[] byteArray = stream.toByteArray();
                            //convert the byte array to a base64 string
                            String base64 = Base64.encodeToString(byteArray, Base64.DEFAULT);
                            //create the html + add the first image to the html
                            String html = "<!DOCTYPE html><html><body bgcolor=\"#7f7f7f\"><img src=\"data:image/png;base64,"+base64+"\" hspace=10 vspace=10><br>";
                            //loop through the rest of the pages and repeat the above
                            for(int i = 2; i <= pdf.getNumPages(); i++)
                            {
                                PDFpage = pdf.getPage(i, true);
                                page = PDFpage.getImage((int)(PDFpage.getWidth() * scale), (int)(PDFpage.getHeight() * scale), null, true, true);
                                stream = new ByteArrayOutputStream();
                                page.compress(Bitmap.CompressFormat.PNG, 100, stream);
                                stream.close();
                                byteArray = stream.toByteArray();
                                base64 = Base64.encodeToString(byteArray, Base64.DEFAULT);
                                html += "<img src=\"data:image/png;base64,"+base64+"\" hspace=10 vspace=10><br>";
                            }
                            html += "</body></html>";
                            //load the html in the webview
                            wv.loadDataWithBaseURL("", html, "text/html","UTF-8", "");
                    }
                    catch (Exception e)
                    {
                        Log.d("CounterA", e.toString());
                    }
                        return null;
                    }
                }.execute();
                System.gc();// run GC
    }
    catch (Exception e)
    {
        Log.d("error", e.toString());
    }
}
string.Empty
  • 10,393
  • 4
  • 39
  • 67
  • I am getting error on this two line ByteBuffer bb = ByteBuffer.NEW(channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size())); PDFFile pdf = new PDFFile(bb); Error on both NEW keyword and PDFFile(bb) so how to solve it – Faiz Anwar Mar 25 '14 at 13:12
0

I like the MuPDF Adnroid lib since it written in C++/NDK and it has unique features like clickable images (I mean an URL linked to the image) - met no other lib with this feature and I was really need it.
You actually can open PDF using no lib at all: using WebView via google docs but I don't like this way due to IC is required all the time while using MuPDF I can DL pdf file and freely open it offline any time. Also WebView way is more "hard" for device meaning battery draining + lags + CPU heating and it uses more trafic (if compared to DL&show way).

Community
  • 1
  • 1
Stan
  • 6,511
  • 8
  • 55
  • 87