Print existing pdf file in android

20,094

Solution 1

Basically I just want to be a able to read in a pdf document and send it as a file output stream directly to the printer to be printed.

That's not strictly possible, unless you find some particular printer that offers such an API for Android.

If you wish to use the Android printing framework, you will need to create a PrintDocumentAdapter that can handle your existing PDF file. This sample project demonstrates one such PrintDocumentAdapter, though it is not general-purpose.

Solution 2

We can simply achieve this by creating a custom PrintDocumentAdapter

PdfDocumentAdapter.java

public class PdfDocumentAdapter extends PrintDocumentAdapter {

Context context = null;
String pathName = "";
public PdfDocumentAdapter(Context ctxt, String pathName) {
    context = ctxt;
    this.pathName = pathName;
}
@Override
public void onLayout(PrintAttributes printAttributes, PrintAttributes printAttributes1, CancellationSignal cancellationSignal, LayoutResultCallback layoutResultCallback, Bundle bundle) {
    if (cancellationSignal.isCanceled()) {
        layoutResultCallback.onLayoutCancelled();
    }
    else {
        PrintDocumentInfo.Builder builder=
                new PrintDocumentInfo.Builder(" file name");
        builder.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
                .setPageCount(PrintDocumentInfo.PAGE_COUNT_UNKNOWN)
                .build();
        layoutResultCallback.onLayoutFinished(builder.build(),
                !printAttributes1.equals(printAttributes));
    }
}

@Override
public void onWrite(PageRange[] pageRanges, ParcelFileDescriptor parcelFileDescriptor, CancellationSignal cancellationSignal, WriteResultCallback writeResultCallback) {
    InputStream in=null;
    OutputStream out=null;
    try {
        File file = new File(pathName);
        in = new FileInputStream(file);
        out=new FileOutputStream(parcelFileDescriptor.getFileDescriptor());

        byte[] buf=new byte[16384];
        int size;

        while ((size=in.read(buf)) >= 0
                && !cancellationSignal.isCanceled()) {
            out.write(buf, 0, size);
        }

        if (cancellationSignal.isCanceled()) {
            writeResultCallback.onWriteCancelled();
        }
        else {
            writeResultCallback.onWriteFinished(new PageRange[] { PageRange.ALL_PAGES });
        }
    }
    catch (Exception e) {
        writeResultCallback.onWriteFailed(e.getMessage());
        Logger.logError( e);
    }
    finally {
        try {
            in.close();
            out.close();
        }
        catch (IOException e) {
            Logger.logError( e);
        }
    }
}}

Now call print by using PrintManager

        PrintManager printManager=(PrintManager) getActivityContext().getSystemService(Context.PRINT_SERVICE);
    try
    {
        PrintDocumentAdapter printAdapter = new PdfDocumentAdapter(Settings.sharedPref.context,filePath );
        }
        printManager.print("Document", printAdapter,new PrintAttributes.Builder().build());
    }
    catch (Exception e)
    {
        Logger.logError(e);
    }

Solution 3

For those interested in the kotlin version of the Karthik Bollisetti answer here is it.

The PdfDocumentAdapter is re-written as this

class PdfDocumentAdapter(private val pathName: String) : PrintDocumentAdapter() {

override fun onLayout(
    oldAttributes: PrintAttributes?,
    newAttributes: PrintAttributes,
    cancellationSignal: CancellationSignal?,
    callback: LayoutResultCallback,
    bundle: Bundle
) {
    if (cancellationSignal?.isCanceled == true) {
        callback.onLayoutCancelled()
        return
    } else {
        val builder = PrintDocumentInfo.Builder(" file name")
        builder.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
            .setPageCount(PrintDocumentInfo.PAGE_COUNT_UNKNOWN)
            .build()

        callback.onLayoutFinished(builder.build(), newAttributes == oldAttributes)
    }
}

override fun onWrite(
    pageRanges: Array<out PageRange>,
    destination: ParcelFileDescriptor,
    cancellationSignal: CancellationSignal?,
    callback: WriteResultCallback
) {
    try {
        // copy file from the input stream to the output stream
        FileInputStream(File(pathName)).use { inStream ->
            FileOutputStream(destination.fileDescriptor).use { outStream ->
                inStream.copyTo(outStream)
            }
        }

        if (cancellationSignal?.isCanceled == true) {
            callback.onWriteCancelled()
        } else {
            callback.onWriteFinished(arrayOf(PageRange.ALL_PAGES))
        }

    } catch (e: Exception) {
        callback.onWriteFailed(e.message)
    }
}
}

then call the PrintManager in your code like this

val printManager : PrintManager = requireContext().getSystemService(Context.PRINT_SERVICE) as PrintManager
try {
    val printAdapter = PdfDocumentAdapter(file.absolutePath)
    printManager.print("Document", printAdapter, PrintAttributes.Builder().build())
} catch (e : Exception) {
    Timber.e(e)
}
Share:
20,094
Doug Ray
Author by

Doug Ray

Updated on July 09, 2022

Comments

  • Doug Ray
    Doug Ray almost 2 years

    Hey everyone so I am trying to build a small sample printing app on android and can't seem to print an existing pdf. There is plenty of documentation on creating a custom document with the canvas but I already have the document. Basically I just want to be a able to read in a pdf document and send it as a file output stream directly to the printer to be printed. Any help is appreciated.