简体   繁体   English

如何在Android中打开WebView中的本地PDF文件?

[英]How to open local PDF file in WebView in Android?

I want to open local (SD card) PDF file in a WebView.我想在WebView中打开本地(SD卡)PDF文件。

I already tried this:我已经尝试过这个:

webview = (WebView) findViewById(R.id.webview);
webview.getSettings().setJavaScriptEnabled(true);
webview.getSettings().setPluginsEnabled(true);
webview.getSettings().setAllowFileAccess(true);
File file = new File(Environment.getExternalStorageDirectory() + "/test.pdf");

final Uri uri = Uri.fromFile(file);

webview.loadUrl(uri.toString());

But it's still not opening it, so let me know how I can open a PDF in WebView?但是还是打不开,请教我如何在WebView中打开一个PDF?

I know, this question is old.我知道,这个问题很老了。

But I really like the approach of Xamarin to make use of the pdf.js from Mozilla.但我真的很喜欢 Xamarin 使用 Mozilla 的 pdf.js 的方法。 It works on older Android versions, you don't need a special PDF Viewer app for this and you can easily display a PDF inside of your apps views hierarchy.它适用于较旧的 Android 版本,您不需要特殊的 PDF 查看器应用程序,您可以轻松地应用程序视图层次结构显示 PDF。

Git for this: https://mozilla.github.io/pdf.js/ Git: https : //mozilla.github.io/pdf.js/

Additional default options (like standard zoom): https://github.com/mozilla/pdf.js/wiki/Viewer-options其他默认选项(如标准缩放): https : //github.com/mozilla/pdf.js/wiki/Viewer-options

Just add the pdfjs files to your Assets directory:只需将 pdfjs 文件添加到您的资产目录:

在此处输入图片说明

And call it the following way:并按以下方式调用它:

// Assuming you got your pdf file:
File file = new File(Environment.getExternalStorageDirectory() + "/test.pdf");

webview = (WebView) findViewById(R.id.webview);
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowUniversalAccessFromFileURLs(true);
settings.setBuiltInZoomControls(true);
webview.setWebChromeClient(new WebChromeClient());
webview.loadUrl("file:///android_asset/pdfjs/web/viewer.html?file=" + file.getAbsolutePath() + "#zoom=page-width");

Cool thing: If you want to reduce the amount of functionalities / controls.很酷的事情:如果你想减少功能/控件的数量。 Go to the Assets/pdfjs/web/viewer.html file and mark certain controls as hidden.转到 Assets/pdfjs/web/viewer.html 文件并将某些控件标记为隐藏。 With

style="display: none;"

Eg If you don't like the right toolbar:例如,如果您不喜欢正确的工具栏:

<div id="toolbarViewerRight" style="display: none;">...</div>

Update更新

'URL scheme "file" is not supported' '不支持 URL 方案“文件”'

Might occur for newer versions of pdfjs.较新版本的 pdfjs 可能会发生。 With version 1.8.188 this error does not appear.1.8.188版本中不会出现此错误。

As @Sameer replied in your comment above, the only solution to view PDF in webview is through Google Docs' online viewer which will render and send back a readable version to your app.正如@Sameer 在您上面的评论中所回答的那样,在 webview 中查看 PDF 的唯一解决方案是通过 Google Docs 的在线查看器,它将呈现并向您的应用发送一个可读版本。

Previously discussed here以前在这里讨论过

You cannot.你不能。 Using an Intent, you can open the PDF in an external viewer application like Acrobat Reader:使用 Intent,您可以在 Acrobat Reader 等外部查看器应用程序中打开 PDF:

try
{
 Intent intentUrl = new Intent(Intent.ACTION_VIEW);
 intentUrl.setDataAndType(uri, "application/pdf");
 intentUrl.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
 mActivity.startActivity(intentUrl);
}
catch (ActivityNotFoundException e)
{
 Toast.makeText(mActivity, "No PDF Viewer Installed", Toast.LENGTH_LONG).show();
}

After going through several posts I came across this simple answer on Quora which pretty much do the work.在浏览了几篇文章后,我在 Quora 上发现了这个简单的答案,它几乎可以完成工作。 Following are steps:-以下是步骤:-

Add this dependency in your gradle file:在您的 gradle 文件中添加此依赖项:

compile 'com.github.barteksc:android-pdf-viewer:2.0.3'

activity_main.xml活动_main.xml

 <com.github.barteksc.pdfviewer.PDFView
    android:id="@+id/pdfView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
     />

MainActivity.java主活动.java

package pdfviewer.pdfviewer;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener;
import com.github.barteksc.pdfviewer.listener.OnPageChangeListener;
import com.github.barteksc.pdfviewer.scroll.DefaultScrollHandle;
import com.shockwave.pdfium.PdfDocument;

import java.util.List;

public class MainActivity extends Activity implements OnPageChangeListener,OnLoadCompleteListener{
    private static final String TAG = MainActivity.class.getSimpleName();
    public static final String SAMPLE_FILE = "sample_pdf.pdf";
    PDFView pdfView;
    Integer pageNumber = 0;
    String pdfFileName;

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


        pdfView= (PDFView)findViewById(R.id.pdfView);
        displayFromAsset(SAMPLE_FILE);
    }

    private void displayFromAsset(String assetFileName) {
        pdfFileName = assetFileName;

        pdfView.fromAsset(SAMPLE_FILE)
                .defaultPage(pageNumber)
                .enableSwipe(true)

                .swipeHorizontal(false)
                .onPageChange(this)
                .enableAnnotationRendering(true)
                .onLoad(this)
                .scrollHandle(new DefaultScrollHandle(this))
                .load();
    }


    @Override    public void onPageChanged(int page, int pageCount) {
        pageNumber = page;
        setTitle(String.format("%s %s / %s", pdfFileName, page + 1, pageCount));
    }


    @Override    public void loadComplete(int nbPages) {
        PdfDocument.Meta meta = pdfView.getDocumentMeta();
        printBookmarksTree(pdfView.getTableOfContents(), "-");

    }

    public void printBookmarksTree(List<PdfDocument.Bookmark> tree, String sep) {
        for (PdfDocument.Bookmark b : tree) {

            Log.e(TAG, String.format("%s %s, p %d", sep, b.getTitle(), b.getPageIdx()));

            if (b.hasChildren()) {
                printBookmarksTree(b.getChildren(), sep + "-");
            }
        }
    }

}

You have to make sure that your asset folder contains sample_pdf.pdf (Library also support opening pdf from Uri and SDCard)您必须确保您的资产文件夹包含 sample_pdf.pdf(库也支持从 Uri 和 SDCard 打开 pdf)

在此处输入图片说明

Happy coding :)快乐编码:)

From android OS 5.0(lollipop) on-wards you can use PdfRenderer instead of webview/library.从 android OS 5.0(lollipop) 开始,您可以使用PdfRenderer instead of webview/library. You can use this class to show pdf's within the app.您可以使用此类在应用程序中显示 pdf。

If you want to support OS lower than that you can use a library/other approach mentioned in other answer as there is no native support.如果您想支持低于该操作系统的操作系统,您可以使用其他答案中提到的库/其他方法,因为没有本机支持。

Read more about it from the docs , you can also refer this example文档中阅读更多关于它的信息,你也可以参考这个例子

you can use the SkewPdfView library for loading pdf from remote or local urls.您可以使用 SkewPdfView 库从远程或本地 url 加载 pdf。

First of all, Add following in your root build.gradle:首先,在您的根 build.gradle 中添加以下内容:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

and add the SkewPdfView Library as:并将SkewPdfView库添加为:

dependencies {
    implementation 'com.github.naya-aastra:SkewPdfView:1.1'
}

Now Include SkewPdfView in your layout:现在在您的布局中包含 SkewPdfView:

<com.nayaastra.skewpdfview.SkewPdfView
    android:id="@+id/skewPdfView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

Save all the local files in assets folder and then use SkewPdfView as follows.将所有本地文件保存在 assets 文件夹中,然后使用 SkewPdfView 如下。 Load a PDF file programmatically as:以编程方式加载 PDF 文件,如下所示:

SkewPdfView skewPdfView;
skewPdfView = findViewById(R.id.skewPdfView);
String pdfLink = "LINK TO ASSET FILE";
skewPdfView.loadPdf(pdfLink);

PS link of SkewPdfView library SkewPdfView 库的 PS 链接

SkewPdfView Github Page SkewPdfView Github 页面

WebView can easily be used for displaying PDF file from a web url but if you have local PDF file, then it becomes a pain. WebView 可以很容易地用于从 web url 显示 PDF 文件,但如果您有本地 PDF 文件,那么它就会变得很痛苦。

In my case i first stored a reference of my local file:-就我而言,我首先存储了本地文件的引用:-

File file = new File(getExternalFilesDir(null),"your_pdf_file.pdf");

Then i obtained file path URI of my local PDF file using FileProvider and started an intent for opening it using existing applications that can open PDF documents:-然后我使用 FileProvider 获取了本地 PDF 文件的文件路径 URI,并开始使用可以打开 PDF 文档的现有应用程序打开它:-

try{
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(FileProvider.getUriForFile(BaseActivity.this,BuildConfig.APPLICATION_ID +".provider",file), "application/pdf");
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    startActivity(intent);
    } catch (ActivityNotFoundException e) {
    Toast.makeText(BaseActivity.this,"No Application Available to View PDF",Toast.LENGTH_SHORT).show();
    }

Also to use FileProvider API, you need to declare it in manifest as:-同样要使用 FileProvider API,您需要在清单中将其声明为:-

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

And declare file_paths.xml under XML resource folder as:-并将 XML 资源文件夹下的 file_paths.xml 声明为:-

<paths>
    <external-path name="external_files" path="."/>
</paths>

WebView don't provide direct functionality to open PDF from local storage. WebView不提供从本地存储打开 PDF的直接功能。 You can open pdf in external PDFViewer applications .您可以在外部PDFViewer 应用程序中打开 pdf。

Wait it will take user to different application .等待它将用户带到不同的应用程序

Now without using any extra library to open a PDF we can use PdfRenderer class to render a PDF.现在不使用任何额外的库来打开PDF ,我们可以使用PdfRenderer class 来渲染 PDF。

PdfRenderer can render pdf on bitmap . PdfRenderer可以在 bitmap 上渲染pdf Bitmap can be drawn to Image View to show the PDF in your application.可以将 Bitmap 绘制到图像视图以在您的应用程序中显示PDF

// create a new renderer
 PdfRenderer renderer = new PdfRenderer(getSeekableFileDescriptor());

 // let us just render all pages
 final int pageCount = renderer.getPageCount();
 for (int i = 0; i < pageCount; i++) {
     Page page = renderer.openPage(i);

     // say we render for showing on the screen
     page.render(mBitmap, null, null, Page.RENDER_MODE_FOR_DISPLAY);

     // do stuff with the bitmap

     // close the page
     page.close();
 }

 // close the renderer
 renderer.close();

Read more about it from the docs .文档中阅读更多相关信息。

WebView can not open a .pdf file. WebView 无法打开 .pdf 文件。 The most popular solution (google docs' url + your url in WebView) just shows you converted by google docs pictures.最流行的解决方案(google docs 的 url + 您在 WebView 中的 url)只显示由 google docs 图片转换的您。 However there is still no simple way to open .pdf from url.但是仍然没有简单的方法可以从 url 打开 .pdf。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM