如何在Webview中显示pdf文档?


114

我想在Webview上显示pdf内容。这是我的代码:

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

我出现黑屏。我还设置了互联网许可。

Answers:


168

您可以使用Google PDF Viewer在线阅读pdf:

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);

1
嗨,sunit,到目前为止,如果您想阅读PDF,则必须在Android手机上安装PDF阅读器,或者使用webview在线呈现PDF文件。抱歉,我们不能使用第二种方法离线读取PDF。
anticafe 2011年

45
经过2天的持续测试,我在Google文档上看到一条错误消息You've reached the bandwidth limit for viewing or downloading files that aren't in Google Docs format....。因此似乎并不可靠。
Shobhit Puri 2014年

4
文档网址现在重定向到云端硬盘:“ drive.google.com/viewerng/viewer?embedded=true&url=
Murphy

31
这个解决方案绝对是可怕的。你们中许多人考虑将丑陋的东西放入您的应用程序这一事实令我感到担忧。此页面是为桌面设计的。该站点显然已针对桌面进行了优化。在移动设备上使用它不是一个好的移动体验。
clu

3
如果您离线,该怎么办?
yerlilbilgin

35

如果您使用仅查看网址,则用户不支持登录该google帐户。

https://docs.google.com/viewer?url=http://my.domain.com/yourPdfUrlHere.pdf

9

就用户体验而言,使用google docs打开pdf是一个坏主意。这真的很慢而且没有反应。

API 21之后的解决方案

从api 21开始,我们有了PdfRenderer,可帮助将pdf转换为Bitmap。我从未使用过它,但是似乎很容易。

适用于任何API级别的解决方案

其他解决方案是下载PDF,并将其通过Intent传递到专用的PDF应用程序,该应用程序会显示它。快速而良好的用户体验,尤其是如果该功能不是您应用程序的核心。

使用此代码下载并打开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);
                    }
                }
            });
}

}

为了使Intent发挥作用,您需要创建一个FileProvider来授予接收应用程序打开文件的权限。

实现方法如下:在清单中:

    <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>

最后在资源管理器中创建一个file_paths.xml文件

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

希望这可以帮助=)


1
shared_pdf是资产下的目录吗?
codezombie

1
这是一个很好的解决方案。
codezombie

9

使用此代码:

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 kidilam答案
Samwinishere这里

7

在这里加载progressDialog。需要提供WebClient,否则将强制在浏览器中打开:

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);

如何在Webview中启用pdf的搜索功能
Anant Shah

4

您可以使用Mozilla pdf.js项目。基本上它将显示PDF。看他们的例子

我只在浏览器(台式机和移动设备)上使用它,并且工作正常。


嗨,@ paulo,能否请您提供有关如何在android上使用它的示例?
Khalid ElSayed 2014年

1
@KhalidElSayed,我认为Butelo已成功实现了您的目标:stackoverflow.com/a/21383356/505893
蓝色

pdf.js可以在本地使用吗?我的意思是,它可以用于无法访问Internet但与本地服务器通信的LAN中使用的应用程序吗?
codezombie

2

实际上,所有解决方案都非常复杂,我找到了一个非常简单的解决方案(我不确定它是否可用于所有sdk版本)。它将在预览窗口中打开pdf文档,用户可以在其中查看和保存/共享该文档:

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)
     }
})

(科特琳)


1
可以给我DownloadListener类的示例代码
mohammedragabmohammedborik

@mohammedragabmohammedborik Android中包含DownloadListener类,您不需要任何其他类即可运行上面的代码。
迪翁

2
请注意,仅Android N及更高版本支持ACTION_QUICK_VIEW。
Pumpkee

@pumpkee是的,这对我来说是个问题。我在上面添加了代码,它检查快速查看是否可用。否则,它将在浏览器中打开。
迪翁

0

从此处下载源代码(在webview android中打开pdf

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();
            }
        });
    }
}

你打开谷歌云端硬盘文件,这不是设备的SD卡上像一个任意PDF
OneCricketeer

是的,在此演示中,我正在显示Google驱动器pdf文件。如果要显示sdcard的pdf,请检查此演示。 deepshikhapuri.wordpress.com/2017/04/24/...
迪普希卡普里

0

这是google允许实际使用限制,在您收到注释中提到的错误之前,如果用户将在应用程序中打开一生一次的pdf文件,则我认为它是完全安全的。尽管建议使用Android 5.0 / Lollipop中Android的内置框架来遵循本机方法,但它被称为PDFRenderer


到“ PDFRenderer”的链接已断开。
Nate

@Nate感谢您的关注,我真的很喜欢它,我已经更新了链接,由于PDF渲染器是本机android API,他们已经移动了网站中的内容,因此,如果将来再次断开更新的链接,它将是最好在Android开发人员网站上进行搜索。
Mightian

0
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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.