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

15,960

Solution 1

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.

Solution 2

I faced with same problem using Android-pdf.js There was blank screen on android 4.x, but the number of pages was correct, so JS can load file from sdcard without any manipulation with base64 and it just rendering problem.

I replaced

  • compatibility.js
  • pdf.js
  • pdf.worker.js

with files from buleto/PDFViewer and it works.

Also I do a little changes in customview.js1 so now url pass using loadUrl\evaluateJavascript instead replacing string in html file. It works for me. You can take changes here: gist

Solution 3

Edit pdf.worker.js in line 1446

if (typeof Blob !== 'undefined') {
    try {return new Blob([data], { type: contentType });}
    catch(e)
    {return null;}
}
Share:
15,960
Riddhish.Chaudhari
Author by

Riddhish.Chaudhari

Updated on July 25, 2022

Comments

  • Riddhish.Chaudhari
    Riddhish.Chaudhari almost 2 years

    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?