大家好,我正在尝试在Android上构建一个小型示例打印应用程序,但似乎无法打印现有的PDF文件。有许多关于使用画布创建自定义文档的文档,但我的文档已经存在。基本上,我只想读取一个PDF文档,并将其作为文件输出流直接发送到打印机进行打印。任何帮助都将不胜感激。
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);
}
}
}}
现在通过使用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);
}
PdfDocumentAdapter
所涉及的所有内容需要大约八页,因此这对于Stack Overflow的回答来说太长了。简而言之,ThreadedPrintDocumentAdapter
将onLayout()
和onWrite()
调用捆绑到LayoutJob
和WriteJob
对象中,并将它们放入工作队列以供后台线程使用。PdfDocumentAdapter
创建自定义作业子类,编写一个罐装的PDF文件(来自assets/
)。 - CommonsWarein=ctxt.getAssets().open("cover.pdf");
更改为使用 FileInputStream
的内容即可。 - CommonsWare对于那些对Karthik Bollisetti的答案的kotlin版本感兴趣的人,这是它。
PdfDocumentAdapter
被重写为:
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)
}
}
}
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)
}
对于支持ipp和pdf的打印机使用情况,您可以使用我的库https://github.com/gmuth/ipp-client-kotlin直接将pdf发送到打印机:
Kotlin:
val printer = IppPrinter(URI.create("ipp://myprinter/ipp"))
val job = printer.printJob(File("mydocument.pdf"))
job.waitForTermination()
不涉及打印对话框。