Print existing pdf file in android

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

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.


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