136

I want to display pdf contents on webview. Here is my code:

WebView webview = new WebView(this); 
setContentView(webview);
webview.getSettings().setJavaScriptEnabled(true); 
webview.loadUrl("http://www.adobe.com/devnet/acrobat/pdfs/pdf_open_parameters.pdf");

I am getting a blank screen. I have set internet permission also.

Diego Palomar
  • 6,958
  • 2
  • 31
  • 42
shriya
  • 1,385
  • 2
  • 9
  • 3

12 Answers12

197

You can use Google PDF Viewer to read your pdf online:

WebView webview = (WebView) findViewById(R.id.webview);
webview.getSettings().setJavaScriptEnabled(true); 
String pdf = "http://www.adobe.com/devnet/acrobat/pdfs/pdf_open_parameters.pdf";
webview.loadUrl("https://drive.google.com/viewerng/viewer?embedded=true&url=" + pdf);
Jaydip
  • 592
  • 5
  • 27
anticafe
  • 6,816
  • 9
  • 43
  • 74
  • you use Google docs to read pdf online, how to read pdf offline on webview in android. – Sunit Kumar Gupta Jun 06 '11 at 09:05
  • 1
    hi sunit, until now if you want to read PDF, you must install a PDF reader on your Android phone, or use webview to render PDF file online. Sorry but we cannot use the second method to read PDF offline. – anticafe Jun 06 '11 at 10:23
  • @Sreeram, Well it's been reliable since March 2011 that's atleast 2 years of reliability. I'd say that's pretty good. :) – Rymnel Apr 04 '13 at 22:26
  • Just wanted to add that most Android distributions now a days (today is 14 Nov 2013) come with a default PDF viewer which will open inside the app. E.g. on Vanilla Android it's QuickOffice, on TouchWiz it's Polaris Office, so you can just start an Intent with the URI of the PDF and it'll open in that PDF viewer - http://stackoverflow.com/questions/2883355/how-to-render-pdf-in-android/2885744. Note, you'll have to download the file to external storage first but is a very native looking solution – jklp Nov 13 '13 at 22:18
  • And all of this solutions are crashes when you try load PDF from sdcard storage – Dmitry Nelepov Jan 14 '14 at 05:58
  • A bit late, but one issue I've had with Google Reader is that it doesn't convert things like %23 (the # character) directly from the URL. You might have to plug your URL into https://docs.google.com/viewer to find the suitable URL for it. – Muz Oct 12 '14 at 07:37
  • 61
    After testing it persistently for 2 days, I got an error on Google docs saying `You've reached the bandwidth limit for viewing or downloading files that aren't in Google Docs format....`. So doesn't seem reliable. – Shobhit Puri Nov 07 '14 at 15:33
  • 6
    The Docs url is now redirecting to Drive: "https://drive.google.com/viewerng/viewer?embedded=true&url=" – Murphy Dec 26 '14 at 22:02
  • Thanks @Murphy. I have used the URL "drive.google.com/viewerng/viewer?embedded=true&url="+pdf_path to view the pdf. – sayani Nov 03 '15 at 12:09
  • 1
    my pdf is not scrolling using webview – shivani gupta Jan 07 '16 at 07:43
  • This is not working with lollipop device. Its redirect to browser. Can you provide solution for lollipop device. – Ankit Thakkar Mar 10 '16 at 06:56
  • i tried opening a pdf file from getExternalStorageDirectory() but it only display a blank page. What should I do? – Kairi San Apr 09 '16 at 16:30
  • 65
    This solution is absolutely terrible. The fact that so many of you consider putting something this ugly in your app worries me. This page is designed for desktop. This site is clearly optimized for desktop. Using this on mobile is not a good mobile experience. – b.lyte Apr 29 '16 at 23:58
  • 1
    it is not working for me. it shows no preview available – Anbarasu Chinna Aug 03 '16 at 07:25
  • Is there any way to use the same approach(loading the pdf using `WebView`) on locally stored PDF document? – micnoy Mar 28 '17 at 08:01
  • 1
    Hi guys, how to deal with this problem if the url to be executed must include authorization header? – KirbyAbadilla Jul 13 '17 at 06:00
  • 8
    what if you are offline? – yerlilbilgin Jan 05 '19 at 00:54
  • 5
    @LyteSpeed Wonder what makes us put such ugly workarounds in our apps? Yeah, you already know; Google's big brain Android team – Farid Feb 24 '21 at 17:27
  • @ShobhitPuri do you have any idea if we will still get `You've reached the bandwidth limit for viewing or downloading files that aren't in Google Docs format....` error or not and what is the solution for this?? – Vivek Thummar Mar 16 '22 at 05:36
  • @VivekThummar Its been so long, I'm not sure now – Shobhit Puri Mar 17 '22 at 06:03
42

If you use the view only url the user is not prompted to login to their google account.

https://docs.google.com/viewer?url=http://my.domain.com/yourPdfUrlHere.pdf
slott
  • 3,266
  • 1
  • 35
  • 30
15

Opening a pdf using google docs is a bad idea in terms of user experience. It is really slow and unresponsive.

Solution after API 21

Since api 21, we have PdfRenderer which helps converting a pdf to Bitmap. I've never used it but is seems easy enough.

Solution for any api level

Other solution is to download the PDF and pass it via Intent to a dedicated PDF app which will do a banger job displaying it. Fast and nice user experience, especially if this feature is not central in your app.

Use this code to download and open the PDF

public class PdfOpenHelper {

public static void openPdfFromUrl(final String pdfUrl, final Activity activity){
    Observable.fromCallable(new Callable<File>() {
        @Override
        public File call() throws Exception {
            try{
                URL url = new URL(pdfUrl);
                URLConnection connection = url.openConnection();
                connection.connect();

                // download the file
                InputStream input = new BufferedInputStream(connection.getInputStream());
                File dir = new File(activity.getFilesDir(), "/shared_pdf");
                dir.mkdir();
                File file = new File(dir, "temp.pdf");
                OutputStream output = new FileOutputStream(file);

                byte data[] = new byte[1024];
                long total = 0;
                int count;
                while ((count = input.read(data)) != -1) {
                    total += count;
                    output.write(data, 0, count);
                }

                output.flush();
                output.close();
                input.close();
                return file;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<File>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {

                }

                @Override
                public void onNext(File file) {
                    String authority = activity.getApplicationContext().getPackageName() + ".fileprovider";
                    Uri uriToFile = FileProvider.getUriForFile(activity, authority, file);

                    Intent shareIntent = new Intent(Intent.ACTION_VIEW);
                    shareIntent.setDataAndType(uriToFile, "application/pdf");
                    shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    if (shareIntent.resolveActivity(activity.getPackageManager()) != null) {
                        activity.startActivity(shareIntent);
                    }
                }
            });
}

}

For the Intent to work, you need to create a FileProvider to grant permission to the receiving app to open the file.

Here is how you implement it: In your Manifest:

    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">

        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />

    </provider>

Finally create a file_paths.xml file in the resources foler

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <files-path name="shared_pdf" path="shared_pdf"/>
</paths>

Hope this helps =)

Community
  • 1
  • 1
JDenais
  • 2,956
  • 2
  • 21
  • 30
15

Use this code

private void pdfOpen(String fileUrl){

        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setPluginState(WebSettings.PluginState.ON);

        //---you need this to prevent the webview from
        // launching another browser when a url
        // redirection occurs---
        webView.setWebViewClient(new Callback());

        webView.loadUrl(
                "http://docs.google.com/gview?embedded=true&url=" + fileUrl);

    }

    private class Callback extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(
                WebView view, String url) {
            return (false);
        }
    }
Athira
  • 1,177
  • 3
  • 13
  • 35
7

You can use the Mozilla pdf.js project. Basically it will show you the PDF. Take a look at their example.

I only use it on the browser (desktop and mobile) and it's working fine.

Sandeep Yohans
  • 929
  • 1
  • 14
  • 36
Paulo Fidalgo
  • 21,709
  • 7
  • 99
  • 115
  • hi @paulo can you please provide me with example about how to use this with the android? – Khalid ElSayed Jun 02 '14 at 11:23
  • 1
    @KhalidElSayed I think that butelo has succeded in your aim: http://stackoverflow.com/a/21383356/505893 – bluish Jun 18 '14 at 13:27
  • Can pdf.js be used locally? I mean can it be used in an application that is used in a LAN with no Internet access, but communicates with a local server? – Mehdi Haghgoo Dec 19 '17 at 08:00
7

Here load with progressDialog. Need to give WebClient otherwise it force to open in browser:

final ProgressDialog pDialog = new ProgressDialog(context);
    pDialog.setTitle(context.getString(R.string.app_name));
    pDialog.setMessage("Loading...");
    pDialog.setIndeterminate(false);
    pDialog.setCancelable(false);
    WebView webView = (WebView) rootView.findViewById(R.id.web_view);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            super.onPageStarted(view, url, favicon);
            pDialog.show();
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            pDialog.dismiss();
        }
    });
    String pdf = "http://www.adobe.com/devnet/acrobat/pdfs/pdf_open_parameters.pdf";
    webView.loadUrl("https://drive.google.com/viewerng/viewer?embedded=true&url=" + pdf);
Naveen Kumar M
  • 7,497
  • 7
  • 60
  • 74
3

Actually all of the solutions were pretty complex, and I found a really simple solution (I'm not sure if it is available for all sdk versions). It will open the pdf document in a preview window where the user is able to view and save/share the document:

webView.setDownloadListener(DownloadListener { url, userAgent, contentDisposition, mimetype, contentLength ->
     val i = Intent(Intent.ACTION_QUICK_VIEW)
     i.data = Uri.parse(url)
     if (i.resolveActivity(getPackageManager()) != null) {
            startActivity(i)
     } else {
            val i2 = Intent(Intent.ACTION_VIEW)
            i2.data = Uri.parse(url)
            startActivity(i2)
     }
})

(Kotlin)

Dion
  • 3,145
  • 20
  • 37
  • 1
    can give me example code for DownloadListener class – mohammedragabmohammedborik Jun 13 '19 at 10:17
  • 1
    @mohammedragabmohammedborik The DownloadListener class is included in Android, you don't need any additional classes to run the code above. – Dion Jun 24 '19 at 17:04
  • 2
    Note that ACTION_QUICK_VIEW is only supported from android N and upwards. – pumpkee Sep 20 '19 at 11:53
  • @pumpkee You're right, that caused a problem in my case. I added the code above that it checks if the Quick View is available. Otherwise it would be opened in the browser. – Dion Sep 26 '19 at 12:32
1

This is the actual usage limit that google allows before you get the error mentioned in the comments, if it's a once in a lifetime pdf that the user will open in app then i feel its completely safe. Although it is advised to to follow the the native approach using the built in framework in Android from Android 5.0 / Lollipop, it's called PDFRenderer.

Aniruddha K.M
  • 7,361
  • 3
  • 43
  • 52
  • The link to "PDFRenderer" is broken. – Nate Feb 10 '19 at 00:06
  • @Nate thanks for Bringing this into my attention I really appriciate it, I have updated the link, Since PDF renderer is a native android API, they have moved things in the website , so in future if the updated link is broken again it would be best to search in the Android developer website. – Aniruddha K.M Feb 13 '19 at 06:12
-1
String webviewurl = "http://test.com/testing.pdf";
webView.getSettings().setJavaScriptEnabled(true); 
if(webviewurl.contains(".pdf")){
    webviewurl = "http://docs.google.com/gview?embedded=true&url=" + webviewurl;        }
webview.loadUrl(webviewurl);
jaigish
  • 157
  • 2
  • 4
-1

You can use

webView.getSettings().setJavaScriptEnabled(true);

val url = "http://your.domain.com/your_pdf_urlHere.pdf"
webView.loadUrl("https://docs.google.com/gview?embedded=true&url=$url")

if you want to open nested pdf link in the webview

webView.webViewClient = object : WebViewClient() {
        override fun shouldOverrideUrlLoading( view: WebView, request: WebResourceRequest): Boolean {
            if (request.url.toString().endsWith(".pdf")) {
                val url = "https://docs.google.com/gview?embedded=true&url=${request.url}"
                view.loadUrl(url)
            }
            return false
        }
    }

This won't ask for login google account

Silambarasan Poonguti
  • 9,386
  • 4
  • 45
  • 38
-3

Download source code from here (Open pdf in webview android)

activity_main.xml

<RelativeLayout android:layout_width="match_parent"
                android:layout_height="match_parent"
                xmlns:android="http://schemas.android.com/apk/res/android">

    <WebView
        android:layout_width="match_parent"
        android:background="#ffffff"
        android:layout_height="match_parent"
        android:id="@+id/webview"></WebView>
</RelativeLayout>

MainActivity.java

package com.pdfwebview;

import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class MainActivity extends AppCompatActivity {

    WebView webview;
    ProgressDialog pDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    init();
    listener();
    }

    private void init() {

        webview = (WebView) findViewById(R.id.webview);
        webview.getSettings().setJavaScriptEnabled(true);

        pDialog = new ProgressDialog(MainActivity.this);
        pDialog.setTitle("PDF");
        pDialog.setMessage("Loading...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(false);
        webview.loadUrl("https://drive.google.com/file/d/0B534aayZ5j7Yc3RhcnRlcl9maWxl/view");

    }

    private void listener() {
        webview.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
                pDialog.show();
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                pDialog.dismiss();
            }
        });
    }
}
Anshuman Jaiswal
  • 5,352
  • 1
  • 29
  • 46
Deepshikha Puri
  • 2,104
  • 22
  • 23
  • You're opening a Google Drive file, which is not any PDF like one on the SD card of the device – OneCricketeer Apr 25 '17 at 12:40
  • Yes In this demo I am showing the Google drive pdf file. If you want to show your pdf from sdcard then check this demo. https://deepshikhapuri.wordpress.com/2017/04/24/open-pdf-file-from-sdcard-in-android-programmatically/ – Deepshikha Puri Apr 25 '17 at 16:28
-3

I fixed it using https://developer.adobe.com/document-services/docs/overview/pdf-embed-api/howtos/

    <div id="adobe-dc-view"></div>
    <script>
    $(document).on("click", "#your-id", function() {
    
        var adobeDCView = new AdobeDC.View({ clientId: your - id, divId: "adobe-dc-view" });
        adobeDCView.previewFile({
            content: { location: { url: pdf - url } },
            metaData: { fileName: "name.pdf" }
        }, { embedMode: "FULL_WINDOW", defaultViewMode: "FIT_PAGE", showAnnotationTools: true, showDownloadPDF: true });
    
    })
    </script>
General Grievance
  • 4,555
  • 31
  • 31
  • 45