我正在扩展 PrintDocumentAdapter 以通过云打印将名册信息发送到打印机。一切正常,直到更改设置以减少文档中的页数。
例如,一张 table 可以放在两张 A4 纸上,但需要三张 A5 纸。云打印默认选择 A4,并生成预览。如果页面大小更改为 A5,则会按预期生成具有三页的新预览。如果随后将页面大小更改回 A4,云打印会显示消息“抱歉,这不起作用。再试一次”。并且必须退出。
这似乎是正在发生的事情:
这只会在旧的 PageRange 大于返回的页数时导致错误,但为什么 onWrite() 会被调用无效的 PageRange?
我注意到我的设备上的许多应用程序只是简单地缩放输出,这样页数就不会在不同设置之间发生变化。他们这样做是因为这个问题吗?
public class PrintAdapter extends PrintDocumentAdapter {
private static final String TAG = "PrintAdapter";
private PrintedPdfBuilder mPrintedPdfBuilder;
private int mPages;
public PrintAdapter(PrintedPdfBuilder printedPdfBuilder) {
mPrintedPdfBuilder = printedPdfBuilder;
}
@Override
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
CancellationSignal cancellationSignal, LayoutResultCallback callback,
Bundle extras) {
Log.v(TAG, "onLayout");
// Respond to cancellation request
if (cancellationSignal.isCanceled()) {
callback.onLayoutCancelled();
return;
}
int pages = mPrintedPdfBuilder.getPageCount(newAttributes);
Log.v(TAG, "page count = " + pages);
if (pages > 0) {
// Return print information to print framework
PrintDocumentInfo info = new PrintDocumentInfo
.Builder("print_output.pdf")
.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
.setPageCount(pages)
.build();
// Content layout reflow is complete
callback.onLayoutFinished(info, mPages != pages);
mPages = pages;
} else {
// Otherwise report an error to the print framework
callback.onLayoutFailed("Page count calculation failed.");
}
}
@Override
public void onWrite(PageRange[] ranges, ParcelFileDescriptor destination,
CancellationSignal cancellationSignal, WriteResultCallback callback) {
Log.v(TAG, "onWrite() ranges: " + Arrays.toString(ranges));
// Write PDF document to file
try {
PrintedPdfDocument pdf = mPrintedPdfBuilder.generateDocument(ranges);
// check for cancellation
if (cancellationSignal.isCanceled()) {
callback.onWriteCancelled();
mPrintedPdfBuilder.close();
return;
}
pdf.writeTo(new FileOutputStream(destination.getFileDescriptor()));
} catch (IOException e) {
callback.onWriteFailed(e.toString());
return;
} finally {
mPrintedPdfBuilder.close();
}
PageRange[] writtenPages = mPrintedPdfBuilder.getWrittenPages();
Log.v(TAG, "writtenPages: " + Arrays.toString(writtenPages));
// Signal the print framework the document is complete
callback.onWriteFinished(writtenPages);
}
}
日志猫:
08-28 11:46:44.187 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: onLayout
08-28 11:46:44.276 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: page count = 2
08-28 11:46:44.298 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: onWrite() ranges: [PageRange[0 - 1]]
08-28 11:46:44.512 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: writtenPages: [PageRange[0 - 1]]
08-28 11:46:50.418 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: onLayout
08-28 11:46:50.499 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: page count = 3
08-28 11:46:50.509 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: onWrite() ranges: [PageRange[0 - 1]]
08-28 11:46:50.678 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: writtenPages: [PageRange[0 - 1]]
08-28 11:46:50.918 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: onWrite() ranges: [PageRange[0 - 2]]
08-28 11:46:51.160 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: writtenPages: [PageRange[0 - 2]]
08-28 11:47:34.983 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: onLayout
08-28 11:47:35.049 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: page count = 2
08-28 11:47:35.056 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: onWrite() ranges: [PageRange[0 - 2]]
08-28 11:47:35.248 9714-9714/com.meremammal.www.staffrosterwizard V/PrintAdapter: writtenPages: [PageRange[0 - 1]]
每次设置更改时都会调用 onLayout,但出于某种原因,然后使用之前的 PageRange[] 调用 onWrite
最佳答案
我捕获了 NullPointerException 错误并向用户显示了一条消息以供重试。这将捕获错误并将您的消息与重试按钮一起显示给用户,然后成功,因为 pageRanges 已更新。
@Override
public void onWrite(final PageRange[] pageRanges,
final ParcelFileDescriptor destination,
final CancellationSignal cancellationSignal,
final WriteResultCallback callback) {
// Iterate over each page of the document,
// check if it's in the output range.
int requestedPageCount;
for (int i = 0; i < mTotalPages; i++) {
// Check to see if this page is in the output range.
if (containsPage(pageRanges, i)) {
//########## Add in this Try Catch Block #############
try {
//######################################################
PdfDocument.PageInfo newPage = new PdfDocument.PageInfo.Builder(mPageWidth,
mPageHeight, i).create();
PdfDocument.Page page =
mPDFDocument.startPage(newPage);
if (cancellationSignal.isCanceled()) {
callback.onWriteCancelled();
mPDFDocument.close();
mPDFDocument = null;
return;
}
if (mPrintJobType == PrintType.LIST) {
drawPageList(page, i + 1, (mPageWidth < mPageHeight));
} else {
drawPageDetail(page, i);
}
mPDFDocument.finishPage(page);
//######## Catch the error here and display a message
} catch (NullPointerException e) {
//Catch a known error thrown thrown by pageRanges not being updated in a timely manner.
callback.onWriteFailed("We found a bug in the Android operating system. " +
"Please click Retry to continue.");
return;
}
//##################################################
}
}
// Write PDF document to file
try {
mPDFDocument.writeTo(new FileOutputStream(
destination.getFileDescriptor()));
} catch (IOException e) {
callback.onWriteFailed(e.toString());
return;
} finally {
mPDFDocument.close();
mPDFDocument = null;
}
callback.onWriteFinished(pageRanges);
}