Android'de PDF dosyası nasıl oluşturulur?


213

Android'in kütüphanelerinde PDF desteği yok. Android uygulamalarında PDF dosyaları oluşturmanın herhangi bir yolu var mı?


5
Bu, pdf dosyalarını gösterme için iyi bir örnektir. Bunu kullanmak için aşağıdaki bağlantıda Benioku.txt dosyasına başvurmanız gerekir. github.com/jblough/Android-Pdf-Viewer-Library
Ramesh Akula

1
İşte bu kütüphaneyi kullanmanın bir örneği: stackoverflow.com/a/16294833/2027232
Nicolas Tyler

Yanıtlar:


68

API Seviye 21 (Lollipop) Android bir PdfRenderer sınıfı sağladığından :

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

Daha fazla bilgi için örnek uygulamaya bakın .

Daha eski API'lar için Android PdfViewer kitaplığını öneriyorum , Apache License 2.0 altında lisanslanan çok hızlı ve kullanımı kolay:

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

12
PDFView kitaplığı harika, ancak daha az GPL değil, GNU Genel Halkı altında olduğunu unutmayın. Bu , ticari yazılıma dahil edilmeyi zorlaştırabilir.
Sam

Evet, @Sam haklı. Şahsen, eski Android sürümlerindeki lisans sorunları nedeniyle PDF.js kullanmak zorunda kaldım, ancak oluşturma son derece yavaş ve Java-JavaScript iletişimi nedeniyle çalışması zor.
Miloš Černilovský

1
Daha eski sürümlerde, dosyayı uygulamada bir yere indirip saklamadan göstermenin bir yolu var mı?
Gökhan Arik

1
Kullanarak daha ayrıntılı bir örnek verebilir misiniz PDFView Library? Ne koymalıyız pdfName? Ne işlevleri yapmak onDraw, onLoadve onPageChangebenzeri dinleyici görünüyor? Yardımınız için teşekkürler :)
Triet Doan

2
Cevaba Apache Lisansı 2.0 altında lisanslanan yeni bir PDF kütüphanesi eklendi.
Miloš Černilovský

61

Blogumdan alınmıştır:

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

70
Bu gerçekten çok temiz değil. Birincisi, Google Google Dokümanlar URL'sini değiştirmeye karar verirse uygulamanız bozulur ve kullanıcıların dokümanları tekrar görüntüleyebilmesi için bir güncelleme yapmanız gerekir.
Mark

3
bu sadece ilk sayfayı görüntülememe izin veriyor ve alttaki "İndir" bağlantısı etkin değil ... herhangi bir fikir? Ayrıca, setPluginsEnabled artık WebView sınıfının bir parçası değil gibi görünüyor.
whyoz

7
İnternet bağlantısı yoksa bu çalışmaz ve İNTERNET İzni gerektirir
Mani

4
Eskiden çalışırdı. Ancak son zamanlarda, "Whoops! Bu belgenin önizlemesinde bir sorun oluştu" ifadesini göstermeye devam ediyorum.
Lee Yi Hong

1
Benim için belge yavaş yükleniyor ve kaydırılıyor.
nilsi

33

Bu ve diğer benzer mesajlara verilen cevaplardan hibrit bir yaklaşım yaptım:

Bu çözüm, bir PDF okuyucu uygulamasının yüklü olup olmadığını kontrol eder ve aşağıdakileri yapar: - Bir okuyucu takılıysa, PDF dosyasını cihaza indirin ve bir PDF okuyucu uygulaması başlatın - Okuyucu yüklü değilse, kullanıcıya görüntülemek isteyip istemediğini sorun PDF dosyasını çevrimiçi olarak Google Drive üzerinden gönderme

NOT! Bu çözüm, DownloadManagerAPI9'da (Android 2.3 veya Gingerbread) tanıtılan Android sınıfını kullanır . Bu , Android 2.2 veya önceki sürümlerde çalışmadığı anlamına gelir .

Bu konuda bir blog yazısı yazdı burada ama şeyiyle aşağıda tam kodunu sağladık:

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

}

8

Kaynak kodu buradan indirin ( PDF dosyasını android uygulamamın içinde görüntüle )

Notunuza bu bağımlılığı ekleyin: 'com.github.barteksc: android-pdf-viewer: 2.0.3' derleyin

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

}

ipucu: assetFileNamepdf dosyası assetsklasöre olmalıdır
ahmednabil88

7

Sonunda Android dosya sistemindeki herhangi bir PDF dosyasını açmak için butelo'nun kodunu değiştirebildim pdf.js. Kod GitHub'ımda bulunabilir

Ne yaptım böyle pdffile.jsHTML argümanını okumak için değiştirildi file:

var url = getURLParameter('file');

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

Yapmanız gereken sadece dosya yolunu aşağıdaki index.htmlgibi eklemektir:

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

pathDeğişkeni Adroid dosya sisteminde geçerli bir PDF'yi gösterecek şekilde güncelleyin .


Merhaba Paul, ben de bu örnek kullandık, ama API Seviye 16 WebView boş ekran gösteriyor, bu sorun hakkında herhangi bir olabilir?
Riddhish.Chaudhari

PDF dosyası nerede saklanır? Varlıklar klasöründen pdf yükleyemezsiniz. SD karttan veya uygulamanızın korumalı dahili depolama biriminden yükleme yapabilirsiniz. Ayrıca web görünümüyle ilgili hatalar için logcat'inizi kontrol edin.
Shantanu Paul

Uri yolu = Uri.parse (Environment.getExternalStorageDirectory (). ToString () + "/example4.pdf"); webView.loadUrl ( "file: ///android_asset/pdfviewer/index.html file =?" + yolu);
Riddhish.Chaudhari

@Paul i API 19 ile iyi çalışıyor yukarıdaki kodu kullanıyorum ama aşağıda çalışmıyor. Neden??
Riddhish.Chaudhari

Lütfen Android'in eski sürümleriyle uyumluluk için bunu inceleyin
Shantanu Paul

4

içe aktararak basit bir yöntem kullanabilirsiniz

implementation 'com.github.barteksc:android-pdf-viewer:2.8.2'

ve XML kodu

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

ve yalnızca bir öğe klasörüne dosya bildirip ekleyin ve sadece adı atayın

   PDFView  pdfView=findViewById(R.id.pdfv);       
    pdfView.fromAsset("agl.pdf").load();

PDFlin'i Kotlin'de nasıl ilan edersiniz?
Nicholas Farmer

@NicholasFarmer bu bağlantıyı kontrol edin stackoverflow.com/questions/56613766/…
akshay shetty

7
Sadece dikkatli olun, bu uygulamanızın üstüne 16 ~ 18MB ekleyebilirsiniz. Bu kütüphane PdfiumAndroidzaten 18.4MB olanı kullanıyor
Pierre

ipucu: agl.pdfdosya assetsklasöre olmalıdır
ahmednabil88

1

Buna biraz ışık katmak için Mozilla'nın pdf.js çözümüyle gitmem gerekecekti. İşte zaten iyi yazılmış bir uygulama bağlantısı: https://bitbucket.org/butelo/pdfviewer/ .

Android Etkinliğime eklediğim düzenlemeler şunlardır:

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

İşte yaptığım düzenlemeler pdffile.js:

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

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

1

Wi-Fi kullanarak PDF'yi açmak ve yazdırmak için aşağıdaki kodu kullandım. Tüm kodumu gönderiyorum ve umarım faydalı olur.

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

0

Android web görünümünde pdf belgesini önizlemek için yine de yoktur. Base64 pdf'i önizlemek istiyorsanız. Üçüncü taraf kitaplığı gerektirir.

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

    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.