2010-03-16 58 views
189

我意识到Android没有内置的显示PDF文件的方法。在Android上使用Java渲染PDF文件

如何在Android上使用Java呈现PDF文件?

+5

这是显示PDF文件很好的例子。需要参考以下链接中的Readme.txt文件来使用它。 https://github.com/jblough/Android-Pdf-Viewer-Library – 2012-07-21 10:04:07

+1

这里是一个使用该库的例子:http://stackoverflow.com/a/16294833/2027232 – 2013-05-13 07:45:06

+0

你hva看看https:// stackoverflow.com/questions/22498937/android-display-pdf-received-bytes-from-service-in-web-view-in-android – 2017-10-13 08:49:25

回答

56

Taken from my blog:

public class MyPdfViewActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    WebView mWebView=new WebView(MyPdfViewActivity.this); 
    mWebView.getSettings().setJavaScriptEnabled(true); 
    mWebView.getSettings().setPluginsEnabled(true); 
    mWebView.loadUrl("https://docs.google.com/gview?embedded=true&url="+LinkTo); 
    setContentView(mWebView); 
    } 
} 
+56

这真的不是很干净。首先,如果Google决定更改他们的Google文档网址,那么您的应用将会中断,您必须为用户推送更新以便能够再次查看文档。 – Mark 2013-08-04 20:50:08

+2

这只允许我查看第一页,并且底部的“下载”链接不活跃......任何想法?此外,它似乎像setPluginsEnabled不再是WebView类的一部分。 – whyoz 2014-02-11 01:10:23

+0

有关Google文档查看器的更多信息,请访问:https://docs.google.com/viewer – 2014-05-30 14:04:42

30

我已经做了混合的方法,从一些给这个和其他类似职位的答案:

该解决方案将检查是否安装了PDF阅读器应用程序并执行以下操作: - 如果安装了阅读器,请将PDF文件下载至设备并启动PDF阅读器应用程序 - 如果未安装阅读器,询问用户是否希望通过Google Drive在线查看PDF文件

注意!该解决方案使用Android DownloadManager类,该类是在API9(Android 2.3或姜饼)中引入的。这意味着它不适用于Android 2.2或更早版本。

我写了一篇博客文章对此here,但我已经提供了完整的代码下面的完整性:

public class PDFTools { 
    private static final String GOOGLE_DRIVE_PDF_READER_PREFIX = "http://drive.google.com/viewer?url="; 
    private static final String PDF_MIME_TYPE = "application/pdf"; 
    private static final String HTML_MIME_TYPE = "text/html"; 

    /** 
    * If a PDF reader is installed, download the PDF file and open it in a reader. 
    * Otherwise ask the user if he/she wants to view it in the Google Drive online PDF reader.<br /> 
    * <br /> 
    * <b>BEWARE:</b> This method 
    * @param context 
    * @param pdfUrl 
    * @return 
    */ 
    public static void showPDFUrl(final Context context, final String pdfUrl) { 
     if (isPDFSupported(context)) { 
      downloadAndOpenPDF(context, pdfUrl); 
     } else { 
      askToOpenPDFThroughGoogleDrive(context, pdfUrl); 
     } 
    } 

    /** 
    * Downloads a PDF with the Android DownloadManager and opens it with an installed PDF reader app. 
    * @param context 
    * @param pdfUrl 
    */ 
    @TargetApi(Build.VERSION_CODES.GINGERBREAD) 
    public static void downloadAndOpenPDF(final Context context, final String pdfUrl) { 
     // Get filename 
     final String filename = pdfUrl.substring(pdfUrl.lastIndexOf("/") + 1); 
     // The place where the downloaded PDF file will be put 
     final File tempFile = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), filename); 
     if (tempFile.exists()) { 
      // If we have downloaded the file before, just go ahead and show it. 
      openPDF(context, Uri.fromFile(tempFile)); 
      return; 
     } 

     // Show progress dialog while downloading 
     final ProgressDialog progress = ProgressDialog.show(context, context.getString(R.string.pdf_show_local_progress_title), context.getString(R.string.pdf_show_local_progress_content), true); 

     // Create the download request 
     DownloadManager.Request r = new DownloadManager.Request(Uri.parse(pdfUrl)); 
     r.setDestinationInExternalFilesDir(context, Environment.DIRECTORY_DOWNLOADS, filename); 
     final DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); 
     BroadcastReceiver onComplete = new BroadcastReceiver() { 
      @Override 
      public void onReceive(Context context, Intent intent) { 
       if (!progress.isShowing()) { 
        return; 
       } 
       context.unregisterReceiver(this); 

       progress.dismiss(); 
       long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1); 
       Cursor c = dm.query(new DownloadManager.Query().setFilterById(downloadId)); 

       if (c.moveToFirst()) { 
        int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS)); 
        if (status == DownloadManager.STATUS_SUCCESSFUL) { 
         openPDF(context, Uri.fromFile(tempFile)); 
        } 
       } 
       c.close(); 
      } 
     }; 
     context.registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); 

     // Enqueue the request 
     dm.enqueue(r); 
    } 

    /** 
    * Show a dialog asking the user if he wants to open the PDF through Google Drive 
    * @param context 
    * @param pdfUrl 
    */ 
    public static void askToOpenPDFThroughGoogleDrive(final Context context, final String pdfUrl) { 
     new AlertDialog.Builder(context) 
      .setTitle(R.string.pdf_show_online_dialog_title) 
      .setMessage(R.string.pdf_show_online_dialog_question) 
      .setNegativeButton(R.string.pdf_show_online_dialog_button_no, null) 
      .setPositiveButton(R.string.pdf_show_online_dialog_button_yes, new OnClickListener() { 
       @Override 
       public void onClick(DialogInterface dialog, int which) { 
        openPDFThroughGoogleDrive(context, pdfUrl); 
       } 
      }) 
      .show(); 
    } 

    /** 
    * Launches a browser to view the PDF through Google Drive 
    * @param context 
    * @param pdfUrl 
    */ 
    public static void openPDFThroughGoogleDrive(final Context context, final String pdfUrl) { 
     Intent i = new Intent(Intent.ACTION_VIEW); 
     i.setDataAndType(Uri.parse(GOOGLE_DRIVE_PDF_READER_PREFIX + pdfUrl), HTML_MIME_TYPE); 
     context.startActivity(i); 
    } 
    /** 
    * Open a local PDF file with an installed reader 
    * @param context 
    * @param localUri 
    */ 
    public static final void openPDF(Context context, Uri localUri) { 
     Intent i = new Intent(Intent.ACTION_VIEW); 
     i.setDataAndType(localUri, PDF_MIME_TYPE); 
     context.startActivity(i); 
    } 
    /** 
    * Checks if any apps are installed that supports reading of PDF files. 
    * @param context 
    * @return 
    */ 
    public static boolean isPDFSupported(Context context) { 
     Intent i = new Intent(Intent.ACTION_VIEW); 
     final File tempFile = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "test.pdf"); 
     i.setDataAndType(Uri.fromFile(tempFile), PDF_MIME_TYPE); 
     return context.getPackageManager().queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY).size() > 0; 
    } 

} 
2

要一盏小灯添加到这个问题,我会去与PDF。来自Mozilla的js解决方案。这里是一个已经写得很好的实现的链接:https://bitbucket.org/butelo/pdfviewer/

这里是我在我的Android活动添加编辑:

private String getInternalPDFURL(String interalPDFName){ 
    return "file:///android_asset/pdfviewer/index.html?pdf=" + interalPDFName + ".pdf"; 
} 

下面是我在pdffile.js所做的编辑:

var url = '../' + getPDFURL(); 

function getPDFURL(){ 
    var query = window.location.search.substring(1); 
    var vars = query.split("="); 
    var pdfPage = vars[1]; 
    return pdfPage; 
} 
7

我终于能够修改butelo's code打开任何PDF文件在Android文件系统中使用pdf.js。该代码可以发现on my GitHub

我所做的修改pdffile.js读取HTML参数file这样的:

var url = getURLParameter('file'); 

function getURLParameter(name) { 
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null} 

所以,你需要做的只是追加index.html这样以后的文件路径是什么:

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

更新path变量指向Adroid文件系统中的有效PDF。

+0

嗨保罗,我也使用了这个例子,但它显示在API级别16的WebView的空白屏幕,你可以有任何关于这个问题? – 2014-08-13 06:00:47

+0

pdf文件存储在哪里?您无法从资产文件夹加载PDF。您可以从SD卡或您的应用的受保护的内部存储装载。 同时检查你的logcat与webview有关的任何错误。 – 2014-08-16 02:45:26

+0

Uri path = Uri.parse(Environment.getExternalStorageDirectory()。toString()+“/example4.pdf”); webView。使用loadURL( “?文件:文件///android_asset/pdfviewer/index.html =” +路径); – 2014-08-16 04:23:15

56

由于API级别21(棒棒糖)Android提供了PdfRenderer class

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

有关详细信息,请参阅sample app

对于旧的API,我推荐Android PdfViewer library,它非常快速且易于使用,在Apache许可证2下许可使用。0:

pdfView.fromAsset(String) 
    .pages(0, 2, 1, 3, 3, 3) // all pages are displayed by default 
    .enableSwipe(true) 
    .swipeHorizontal(false) 
    .enableDoubletap(true) 
    .defaultPage(0) 
    .onDraw(onDrawListener) 
    .onLoad(onLoadCompleteListener) 
    .onPageChange(onPageChangeListener) 
    .onPageScroll(onPageScrollListener) 
    .onError(onErrorListener) 
    .enableAnnotationRendering(false) 
    .password(null) 
    .scrollHandle(null) 
    .load(); 
+7

PDFView库很棒,但注意它是在GNU General Public,而不是较小的GPL。这可能会使其很难包含在商业软件中。 – Sam 2015-04-06 16:08:32

+0

是的@Sam是正确的。就个人而言,由于旧版Android版本中的许可问题,我不得不使用PDF.js,但渲染速度非常慢,并且由于Java-JavaScript通信而难以使其工作。 – 2015-04-08 06:11:36

+1

对于旧版本,有没有什么方法可以显示它们,而无需在应用程序某处下载和存储文件? – 2015-04-11 04:05:13

1

我用下面的代码打开并使用Wi-Fi打印PDF。我正在发送我的整个代码,我希望它有帮助。

public class MainActivity extends Activity { 

    int Result_code = 1; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     Button mButton = (Button)findViewById(R.id.button1); 

     mButton.setOnClickListener(new View.OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       // TODO Auto-generated method stub 

       PrintManager printManager = (PrintManager)getSystemService(Context.PRINT_SERVICE); 
       String jobName = " Document"; 
       printManager.print(jobName, pda, null); 
      } 
     }); 
    } 


    public void openDocument(String name) { 

     Intent intent = new Intent(android.content.Intent.ACTION_VIEW); 
     File file = new File(name); 
     String extension = android.webkit.MimeTypeMap.getFileExtensionFromUrl(Uri.fromFile(file).toString()); 
     String mimetype = android.webkit.MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); 
     intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 

     if (extension.equalsIgnoreCase("") || mimetype == null) { 
      // if there is no extension or there is no definite mimetype, still try to open the file 
      intent.setDataAndType(Uri.fromFile(file), "text/*"); 
     } 
     else { 
      intent.setDataAndType(Uri.fromFile(file), mimetype); 
     } 

     // custom message for the intent 
     startActivityForResult((Intent.createChooser(intent, "Choose an Application:")), Result_code); 
     //startActivityForResult(intent, Result_code); 
     //Toast.makeText(getApplicationContext(),"There are no email clients installed.", Toast.LENGTH_SHORT).show(); 
    } 


    @SuppressLint("NewApi") 
    PrintDocumentAdapter pda = new PrintDocumentAdapter(){ 

     @Override 
     public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback){ 
      InputStream input = null; 
      OutputStream output = null; 

      try { 
       String filename = Environment.getExternalStorageDirectory() + "/" + "Holiday.pdf"; 
       File file = new File(filename); 
       input = new FileInputStream(file); 
       output = new FileOutputStream(destination.getFileDescriptor()); 

       byte[] buf = new byte[1024]; 
       int bytesRead; 

       while ((bytesRead = input.read(buf)) > 0) { 
        output.write(buf, 0, bytesRead); 
       } 

       callback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES}); 
      } 
      catch (FileNotFoundException ee){ 
       //Catch exception 
      } 
      catch (Exception e) { 
       //Catch exception 
      } 
      finally { 
       try { 
        input.close(); 
        output.close(); 
       } 
       catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 

     @Override 
     public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras){ 

      if (cancellationSignal.isCanceled()) { 
       callback.onLayoutCancelled(); 
       return; 
      } 

      // int pages = computePageCount(newAttributes); 

      PrintDocumentInfo pdi = new PrintDocumentInfo.Builder("Name of file").setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build(); 

      callback.onLayoutFinished(pdi, true); 
     } 
    }; 
} 
5

这里下载(Display PDF file inside my android application

源代码添加这个依赖于你的成绩: 编译 'com.github.barteksc:Android的PDF查看器:2.0.3'

activity_main.xml中

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

    <TextView 
     android:layout_width="match_parent" 
     android:layout_height="40dp" 
     android:background="@color/colorPrimaryDark" 
     android:text="View PDF" 
     android:textColor="#ffffff" 
     android:id="@+id/tv_header" 
     android:textSize="18dp" 
     android:gravity="center"></TextView> 

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


    </RelativeLayout> 

MainActivity.java

import android.app.Activity; 
import android.database.Cursor; 
import android.net.Uri; 
import android.provider.OpenableColumns; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.View; 
import android.widget.ImageView; 
import android.widget.RelativeLayout; 

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 = "android_tutorial.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 + "-"); 
      } 
     } 
    } 

} 
0

在Android webview中无法预览pdf文档。如果您想预览base64 pdf,它需要第三方库。

的build.gradle

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

dialog_pdf_viewer

<?xml version="1.0" encoding="utf-8"?> 

<!-- 
    ~ Copyright (c) 2017. 
    ~ Samet Öztoprak 
    ~ All rights reserved. 
    --> 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:gravity="center_horizontal" 
    android:orientation="vertical"> 

    <ImageView 
     android:id="@+id/dialog_pdf_viewer_close" 
     style="@style/ExitButtonImageViewStyle" 
     android:src="@drawable/popup_exit" /> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:layout_weight="1" 
     android:background="@color/white" 
     android:orientation="vertical"> 

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

    </LinearLayout> 

    <View style="@style/HorizontalLine" /> 

    <com.pozitron.commons.customviews.ButtonFont 
     android:id="@+id/dialog_pdf_viewer_button" 
     style="@style/ButtonPrimary2" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:padding="15dp" 
     android:text="@string/agreed" /> 

</LinearLayout> 

DailogPDFViewer.java

public class DialogPdfViewer extends Dialog { 
    PDFView pdfView; 
    byte[] decodedString; 

    public interface OnDialogPdfViewerListener { 
     void onAgreeClick(DialogPdfViewer dialogFullEula); 

     void onCloseClick(DialogPdfViewer dialogFullEula); 
    } 

    public DialogPdfViewer(Context context, String base64, final DialogPdfViewer.OnDialogPdfViewerListener onDialogPdfViewerListener) { 
     super(context); 

     setContentView(R.layout.dialog_pdf_viewer); 
     findViewById(R.id.dialog_pdf_viewer_close).setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       onDialogPdfViewerListener.onCloseClick(DialogPdfViewer.this); 
      } 
     }); 

     findViewById(R.id.dialog_pdf_viewer_button).setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       onDialogPdfViewerListener.onAgreeClick(DialogPdfViewer.this); 
      } 
     }); 

     decodedString = Base64.decode(base64.toString(), Base64.DEFAULT); 

     pdfView = ((PDFView) findViewById(R.id.pdfView)); 
     pdfView.fromBytes(decodedString).load(); 

     setOnKeyListener(new OnKeyListener() { 
      @Override 
      public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { 
       if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) { 
        onDialogPdfViewerListener.onCloseClick(DialogPdfViewer.this); 
       } 
       return true; 
      } 
     }); 

    } 
}