2010-03-16 8 views
189

Zdałem sobie sprawę, że Android nie ma wbudowanej metody wyświetlania plików PDF.Renderowanie pliku PDF za pomocą Java na Androida

Jak mogę renderować plik PDF za pomocą Java na Androida?

+5

Jest to dobry przykład dla Pokazuje plików PDF. Aby skorzystać z tej funkcji, musisz odwołać się do pliku Readme.txt poniżej. https://github.com/jblough/Android-Pdf-Viewer-Library –

+1

tutaj jest przykładem korzystania z tej biblioteki: http://stackoverflow.com/a/16294833/2027232 –

+0

you hva patrzeć na https: // stackoverflow.com/questions/22498937/android-display-pdf-received-bytes-from-service-in-web-view-in-android –

Odpowiedz

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

To naprawdę nie jest bardzo czyste. Po pierwsze, jeśli Google kiedykolwiek zdecyduje się na zmianę swojego adresu URL Dokumentów Google, twoja aplikacja się zepsuje i będziesz musiał przesłać aktualizację dla użytkowników, aby móc ponownie wyświetlać dokumenty. – Mark

+2

to tylko pozwala mi zobaczyć pierwszą stronę, a link "Pobierz" na dole nie jest aktywny ... żadnych pomysłów? Wygląda również na to, że setPluginsEnabled nie jest już częścią klasy WebView. – whyoz

+0

Aby uzyskać więcej informacji na temat przeglądarki google docs: https://docs.google.com/viewer –

30

zrobiłem hybrydowe podejście niektórych z odpowiedzi udzielonych na tej i innych podobnych wypowiedzi:

sprawdze to rozwiązanie, jeśli aplikacja PDF Reader jest zainstalowany i wykonuje następujące operacje: - Jeśli zainstalowany jest czytnik, pobierz plik PDF na urządzenie i uruchom aplikację do odczytu plików PDF - Jeśli nie zainstalowano czytnika, poproś użytkownika, czy chce wyświetlić plik PDF online za pośrednictwem Google Drive

UWAGA! To rozwiązanie wykorzystuje klasę Android DownloadManager, która została wprowadzona w API9 (Android 2.3 lub Gingerbread). Oznacza to, że nie działa w systemie Android 2.2 lub wcześniejszym.

napisałem na blogu o tym here, ale podajemy pełny kod poniżej dla kompletności:

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

Aby dodać trochę światła na to, że będę musiał iść z pdf. js rozwiązanie z Mozilli. Oto link do dobrze już napisanej implementacji tego: https://bitbucket.org/butelo/pdfviewer/.

Oto zmiany, które dodałem w moim Android działalność:

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

Oto zmiany zrobiłem w 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

I w końcu był w stanie zmodyfikować butelo's code aby otworzyć dowolny plik PDF plik w systemie plików Android za pomocą pdf.js. Kod można znaleźć on my GitHub

co robiłam został zmodyfikowany pdffile.js czytać argumentu HTML file tak:

var url = getURLParameter('file'); 

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

Więc co trzeba zrobić, to po prostu dołączyć ścieżkę po index.html tak:

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

Aktualizacja zmienna path aby wskazać ważnego PDF w Adroid plików.

+0

hi Paul, użyłem również tego przykładu, ale pokazuje on pusty ekran w WebView na poziomie API 16, czy możesz mieć jakiś problem? –

+0

Gdzie jest przechowywany plik pdf? Nie można załadować pliku pdf z folderu zasobów. Możesz załadować z karty SD lub z chronionej pamięci wewnętrznej aplikacji. Sprawdź również swój logcat pod kątem błędów związanych z widokiem na WWW. –

+0

Ścieżka Uri = Uri.parse (Environment.getExternalStorageDirectory(). ToString() + "/example4.pdf"); webView.loadUrl ("file: ///android_asset/pdfviewer/index.html? file =" + ścieżka); –

56

Ponieważ API poziom 21 (Lollipop) Android zapewnia 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(); 

Aby uzyskać więcej informacji, zobacz sample app.

Dla starszych API polecam Android PdfViewer library, jest bardzo szybki i łatwy w użyciu, na licencji 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(); 
+7

Biblioteka PDFView jest świetna, ale zauważ, że jest pod GNU General Public, a nie Lesser GPL. To * może * utrudniać dołączanie do komercyjnego oprogramowania. – Sam

+0

Tak, @Sam ma rację. Osobiście musiałem używać PDF.js z powodu problemów licencyjnych w starszych wersjach Androida, ale renderowanie jest bardzo powolne i trudno jest to zrobić z powodu komunikacji Java-JavaScript. –

+1

Dla starszych wersji, czy jest jakiś sposób, aby je wyświetlić bez pobierania i przechowywania pliku gdzieś w aplikacji? –

1

Użyłem poniższego kodu, aby otworzyć i wydrukować plik PDF za pomocą Wi-Fi. Wysyłam cały mój kod i mam nadzieję, że będzie pomocny.

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

Pobierz kod źródłowy tutaj (Display PDF file inside my android application)

Dodaj tę zależność w swoim gatunku: kompilacji 'com.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 + "-"); 
      } 
     } 
    } 

} 
0

Nie ma jeszcze podglądu dokumentu PDF w przeglądarce internetowej Android. Jeśli chcesz wyświetlić podgląd bazy64 pdf. To wymaga biblioteki innej firmy.

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

    } 
} 
Powiązane problemy