Android – Show PDF file in Android WebView using mozilla pdf.js Android API Level below 19

androidpdfwebview

I'm using mozilla pdf.js in Android WebView to Show PDF files.

Code is working fine in Android API Level 19.

Uri path = Uri.parse(Environment.getExternalStorageDirectory().toString() + "/test.pdf");
webView.loadUrl("file:///android_asset/pdfviewer/index.html?file=" + path); 

But it's not working on Android API Level 16 and below.

A White blank Screen displays on Device.

Is there any way to resolve this issue?

Best Solution

I've had the same problem. First it seemed that using an older version of pdf.js from December 2013 would work, if instead of including the compiled files (pdf.js and pdf.worker.js) you'd include all the js files separately like in the helloworld example.

Then I discovered this SO post. Someone there has put together a pdf.js example for Android (Butelo). I've tried it, the .js files in the asset folder of the project even work on Android 2.3, but only if accessed over http. In the post there are also suggestions on how to get this to work with file:// urls. I found yet another solution:

You read and convert the PDF file to Base64 with Java. In this way you're circumventing the file:// restriction.

ByteArrayOutputStream ous = null;
InputStream ios = null;
String imageData = null;
try {
    byte[] buffer = new byte[4096];
    ous = new ByteArrayOutputStream();
    ios = new FileInputStream(pdfFile);
    int read = 0;
    while ( (read = ios.read(buffer)) != -1 ) {
        ous.write(buffer, 0, read);
    }                                  
    imageData = Base64.encodeToString(ous.toByteArray(), Base64.DEFAULT).replace("\n", "").replace("\r", "");                                       
} catch (Exception e) {
    e.printStackTrace();
}           

You then load the WebView by somehow passing the imageData to it. With JavaScript you'll need to convert the Base64 to a UInt8 array. Probably you could do this directly in Java and avoid the Base64 detour, but I didn't figure out how and I'm not sure how you'd get that array into your WebView.

function fromBase64(dataURI) {           
    var raw = window.atob(dataURI);
    var rawLength = raw.length;
    var array = new Uint8Array(new ArrayBuffer(rawLength));

    for(i = 0; i < rawLength; i++) {
         array[i] = raw.charCodeAt(i);
    }
    return array;
}

pdf.js will take the UInt8 array like if it was a URL. So you can use:

PDFJS.getDocument(fromBase64(base64DataFromJava));

This method works for sure on Android 4.0 and above. For some strange reason it currently doesn't work on Android 2.3 for me, but that might be related to some other problem in my project. Of course, on older devices, the rendering will take some time (sometimes half a minute), but that'll be the case anyways.

Related Question