使用PrintDocumentAdapter和PrintManager更改页数

时间:2016-08-26 06:56:13

标签: android pdf printing

我正在扩展PrintDocumentAdapter,以通过云打印将名册信息发送到打印机。一切都运行良好,直到更改设置,以减少文档中的页数。

例如,一张桌子适合两个A4页面,但需要三个A5页面。云打印以默认选择的A4开始,并生成预览。如果页面大小更改为A5,则会生成具有三个页面的新预览。如果页面大小随后更改回A4,则云打印会显示消息"抱歉,这不起作用。再试一次。"并且必须退出。

这似乎正在发生:

    使用A4文档属性调用
  • onLayout()。 LayoutResultCallback.onLayoutFinished()传递PrintDocumentInfo pageCount设置为2.
  • 使用单个PageRange 0-1调用onWrite(),如预期的那样。
  • 我将纸张尺寸更改为A5。
  • 使用A5文档属性调用
  • onLayout()。 LayoutResultCallback.onLayoutFinished()传递PrintDocumentInfo pageCount设置为3.
  • 使用单个PageRange 0-1调用onWrite(),这是旧范围
  • onWrite()第二次被调用,正确的PageRange为0-2。

当旧的PageRange大于返回的页数时,这只会导致错误,但为什么使用无效的PageRange调用onWrite()?

我注意到我设备上的许多应用只是缩放输出,因此页数不会在不同设置之间发生变化。他们是否因为这个问题而这样做了?

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

logcat的:

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

2 个答案:

答案 0 :(得分:0)

我捕获了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);
    }

答案 1 :(得分:0)

最后一个打印机区域的成员!

以下内容与“云打印”无关,但仍为那些寻求通过更改打印属性和系统抛出错误而寻求解决方案的人提供答案。

>

更改属性后,从以下选项中,系统抛出错误。

enter image description here

对于使用.fs-font::after的本地打印机请求,以下方法有效。 PrinterDocumentAdapter方法的更改。

onLayout

将返回值的默认实现更改为false。休息系统会注意的。

public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, ....

我正在将InputStream从我的活动发送到“自定义文档”适配器。以下是相同内容的完整来源。

首先从任何位置(内存/资产等)读取内容。接下来使用InputStream显示要打印的文档。

@Override
    public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras) {
        Log.d(TAG,"MyPrintDocumentAdapter onLayout ");
        if (cancellationSignal.isCanceled()) {
            callback.onLayoutCancelled();
            return;
        }
        if (mTotalPages > 0) {
            PrintDocumentInfo.Builder builder = new PrintDocumentInfo
                    .Builder(mFileName)
                    .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
                    .setPageCount(mTotalPages);

            PrintDocumentInfo info = builder.build();
            callback.onLayoutFinished(info, false);// Second param should be false
        } else {
            Log.e(TAG, "onLayout Error in page count");
            callback.onLayoutFailed("Page count is zero.");
        }
    }