在Android上使用Java呈现PDF文件

我意识到Android没有内置的显示PDF文件的方法。

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

从我的博客采取:

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

由于API Level 21(Lollipop)Android提供了一个PdfRenderer类 :

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

欲了解更多信息,请参阅示例应用 。

对于较老的API,我build议使用Android PdfViewer库 ,它非常快速且易于使用,在Apache License 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(); 

我已经从这个和其他类似的post的一些答案混合的方法:

此解决scheme检查是否安装了PDF阅读器应用程序,并执行以下操作: – 如果安装了阅读器,请将PDF文件下载到设备并启动PDF阅读器应用程序 – 如果未安装阅读器,请询问用户是否要浏览通过Google云端硬盘联机的PDF文件

注意! 此解决scheme使用API​​ Download(Android 2.3或Gingerbread)中引入的Android DownloadManager类。 这意味着它不适用于Android 2.2或更早的版本。

我在这里写了一篇关于它的博客文章,但为了完整性,我提供了完整的代码:

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

我终于可以修改butelo的代码 ,使用pdf.js在Android文件系统中打开任何PDF文件。 代码可以在我的GitHub上find

我所做的是修改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之后附加文件path,如下所示:

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

更新pathvariables以指向Adroid文件系统中的有效PDF。

在这里下载源代码( 在我的Android应用程序中显示PDF文件 )

在你的Grade中join这个依赖项:compile'c​​om.github.barteksc:android-pdf-viewer: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 + "-"); } } } } 

为了增加一点光线,我将不得不使用Mozilla的pdf.js解决scheme。 这里是一个已经写得很好的这个实现的链接: https : //bitbucket.org/butelo/pdfviewer/ 。

以下是我在Android Activity中添加的编辑内容:

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

我使用下面的代码打开并使用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); } }; } 

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