Codes to print PDF not working at the last step

huangapple go评论92阅读模式
英文:

Codes to print PDF not working at the last step

问题

我正在编写一个可以创建数学工作表并生成带答案页面的PDF格式的应用程序。我想添加一个打印功能,允许直接从应用程序中打印工作表。

在PrintDocumentAdapter中,代码的前半部分检查页面的特定像素的颜色,以确定它是否是答案页面,并相应地减少要打印的页面数量。然后它构造一个printingPDF文档,并在onWrite()中使用writeTo()方法将其发送打印。

一切都运行得很好,直到最后一部分。它正确读取PDF,正确检查答案页面的数量,并将仅包含问题页面的正确PDF发送到打印页面。如果我在打印页面中选择“另存为PDF”,它会毫无问题地将页面保存到新的PDF文件中。然而,如果我尝试通过点击打印按钮将其打印到连接在手机上的USB打印机上,打印页面会简单地消失并返回到我的应用程序的主页面。(它应该将这几页传递给打印机应用程序。)我尝试了几种不同的安卓打印机驱动应用程序,结果是一样的。

以下是你的代码,我将其翻译成中文:

private void printWS() throws IOException {
    findViewById(R.id.defaultTextView).setVisibility(View.INVISIBLE);
    if (!loadedFile) {
        File file = new File(getApplicationContext().getCacheDir(), getString(R.string.defaultFileName));
        parcelFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
    } else {
        parcelFileDescriptor = getContentResolver().openFileDescriptor(pdfUri, "r");
    }
    
    // 开始打印
    PrintManager printManager = (PrintManager) this.getSystemService(PRINT_SERVICE);
    String jobName = getString(R.string.app_name);
    PrintAttributes printAttributes = new PrintAttributes.Builder().setMediaSize(PrintAttributes.MediaSize.ISO_A4).build();
    printManager.print(jobName, new PrintDocumentAdapter() {
        int finalTotal;

        @Override
        public void onStart() {
            if (parcelFileDescriptor != null) {
                try {
                    pdfRenderer = new PdfRenderer(parcelFileDescriptor);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            int tempTotal = pdfRenderer.getPageCount();
            Bitmap[] tempBitmap = new Bitmap[tempTotal];
            finalTotal = tempTotal;
            for (int pageNum = 0; pageNum < tempTotal; pageNum++) {
                PdfRenderer.Page tempPage = pdfRenderer.openPage(pageNum);
                tempBitmap[pageNum] = Bitmap.createBitmap(WS_WIDTH, WS_HEIGHT, Bitmap.Config.ARGB_8888);
                tempPage.render(tempBitmap[pageNum], null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);
                if (tempBitmap[pageNum].getPixel(0, 0) == Color.GRAY) {
                    finalTotal--;
                }
                tempPage.close();
            }
        }

        PrintedPdfDocument printingPDF;

        @Override
        public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle bundle) {
            printingPDF = new PrintedPdfDocument(getApplicationContext(), newAttributes);
            if (cancellationSignal.isCanceled()) {
                callback.onLayoutCancelled();
                return;
            }
            if (finalTotal > 0) {
                PrintDocumentInfo info = new PrintDocumentInfo
                        .Builder("Worksheet")
                        .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
                        .setPageCount(finalTotal)
                        .build();
                callback.onLayoutFinished(info, true);
            } else {
                callback.onLayoutFailed("Page count calculation failed.");
            }
        }

        @Override
        public void onWrite(PageRange[] pageRanges, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback) {
            Bitmap[] loadedBitmap = new Bitmap[finalTotal];
            for (int pageNum = 0; pageNum < finalTotal; pageNum++) {
                PdfDocument.PageInfo printingPageInfo = new PdfDocument.PageInfo.Builder(WS_WIDTH, WS_HEIGHT, pageNum).create();
                PdfDocument.Page printingPage = printingPDF.startPage(printingPageInfo);
                if (cancellationSignal.isCanceled()) {
                    callback.onWriteCancelled();
                    printingPDF.close();
                    printingPDF = null;
                    return;
                }
                PdfRenderer.Page loadedPage = pdfRenderer.openPage(pageNum);
                loadedBitmap[pageNum] = Bitmap.createBitmap(WS_WIDTH, WS_HEIGHT, Bitmap.Config.ARGB_8888);
                loadedPage.render(loadedBitmap[pageNum], null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);
                Canvas canvas = printingPage.getCanvas();
                Paint paint = new Paint();
                canvas.drawBitmap(loadedBitmap[pageNum], 0, 0, paint);
                printingPDF.finishPage(printingPage);
                loadedPage.close();
            }
            try {
                printingPDF.writeTo(new FileOutputStream(destination.getFileDescriptor()));
            } catch (IOException e) {
                callback.onWriteFailed(e.toString());
                return;
            } finally {
                printingPDF.close();
                printingPDF = null;
            }
            PageRange[] writtenPages = new PageRange[]{PageRange.ALL_PAGES};
            callback.onWriteFinished(writtenPages);
        }

        @Override
        public void onFinish() {
            try {
                pdfRenderer.close();
                parcelFileDescriptor.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }, printAttributes);
}

请问有人能够查看我的代码并告诉我出了什么问题吗?请帮忙,谢谢!

英文:

I am writing an app that can create Maths worksheet with answer pages in PDF format. I want to add a print function to allow printing the worksheet directly from the app.

In the PrintDocumentAdapter, the first half of the codes check the color of a certain pixel of the page to determine whether it is an answer page and reduce the number of pages to print accordingly. It then constructs a printingPDF document and sends it to print using 's writeTo() method in the onWrite().

Everything works fine until the last part. It reads the PDF correctly, checks the number of answer pages correctly, and sends a correct PDF with question pages only to the printing page. If I choose "Save as PDF" in the printing page, it saves the pages to a new PDF file with no problem. However, if I try to print with my printer that is connected to my phone with USB by clicking the print button, the printing page simply disappears and goes back to the main page of my app. (It is supposed to past those few pages to the printer app.) I tried several different android printer driver apps and the result was the same.

private void printWS() throws IOException {
findViewById(R.id.defaultTextView).setVisibility(View.INVISIBLE);
if (!loadedFile) {
File file = new File(getApplicationContext().getCacheDir(), getString(R.string.defaultFileName));
parcelFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
} else {
parcelFileDescriptor = getContentResolver().openFileDescriptor(pdfUri, &quot;r&quot;);
}
// Start printing
PrintManager printManager = (PrintManager) this.getSystemService(PRINT_SERVICE);
String jobName = getString(R.string.app_name);
PrintAttributes printAttributes = new PrintAttributes.Builder().setMediaSize(PrintAttributes.MediaSize.ISO_A4).build();
printManager.print(jobName, new PrintDocumentAdapter() {
int finalTotal;
@Override
public void onStart() {
if (parcelFileDescriptor != null) {
try {
pdfRenderer = new PdfRenderer(parcelFileDescriptor);
} catch (IOException e) {
e.printStackTrace();
}
}
int tempTotal = pdfRenderer.getPageCount();
Bitmap[] tempBitmap = new Bitmap[tempTotal];
finalTotal = tempTotal;
for (int pageNum = 0; pageNum &lt; tempTotal; pageNum++) {
PdfRenderer.Page tempPage = pdfRenderer.openPage(pageNum);
tempBitmap[pageNum] = Bitmap.createBitmap(WS_WIDTH, WS_HEIGHT, Bitmap.Config.ARGB_8888);
tempPage.render(tempBitmap[pageNum], null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);
if (tempBitmap[pageNum].getPixel(0, 0) == Color.GRAY) {
finalTotal--;
}
tempPage.close();
}
}
PrintedPdfDocument printingPDF;
@Override
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle bundle) {
printingPDF = new PrintedPdfDocument(getApplicationContext(), newAttributes);
if (cancellationSignal.isCanceled()) {
callback.onLayoutCancelled();
return;
}
if (finalTotal &gt; 0) {
PrintDocumentInfo info = new PrintDocumentInfo
.Builder(&quot;Worksheet&quot;)
.setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
.setPageCount(finalTotal)
.build();
callback.onLayoutFinished(info, true);
} else {
callback.onLayoutFailed(&quot;Page count calculation failed.&quot;);
}
}
@Override
public void onWrite(PageRange[] pageRanges, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback) {
Bitmap[] loadedBitmap = new Bitmap[finalTotal];
for (int pageNum = 0; pageNum &lt; finalTotal; pageNum++) {
PdfDocument.PageInfo printingPageInfo = new PdfDocument.PageInfo.Builder(WS_WIDTH, WS_HEIGHT, pageNum).create();
PdfDocument.Page printingPage = printingPDF.startPage(printingPageInfo);
if (cancellationSignal.isCanceled()) {
callback.onWriteCancelled();
printingPDF.close();
printingPDF = null;
return;
}
PdfRenderer.Page loadedPage = pdfRenderer.openPage(pageNum);
loadedBitmap[pageNum] = Bitmap.createBitmap(WS_WIDTH, WS_HEIGHT, Bitmap.Config.ARGB_8888);
loadedPage.render(loadedBitmap[pageNum], null, null, PdfRenderer.Page.RENDER_MODE_FOR_PRINT);
Canvas canvas = printingPage.getCanvas();
Paint paint = new Paint();
canvas.drawBitmap(loadedBitmap[pageNum], 0, 0, paint);
printingPDF.finishPage(printingPage);
loadedPage.close();
}
try {
printingPDF.writeTo(new FileOutputStream(destination.getFileDescriptor()));
} catch (IOException e) {
callback.onWriteFailed(e.toString());
return;
} finally {
printingPDF.close();
printingPDF = null;
}
PageRange[] writtenPages = new PageRange[]{PageRange.ALL_PAGES};
callback.onWriteFinished(writtenPages);
}
@Override
public void onFinish() {
try {
pdfRenderer.close();
parcelFileDescriptor.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}, printAttributes);
}

Can someone take a look at my codes and tell me what is going wrong? Please help! Thanks!

答案1

得分: 0

没关系。原来代码是没问题的。我需要做的是进入手机的设置,将打印机驱动程序应用的“在后台运行时显示弹出窗口”更改为“允许”,然后它就完美地运行了!

我会保留这里的问题和答案,以防其他人遇到相同的问题。

英文:

Nevermind. It turned out the codes are ok. What I needed to do was go to the settings of my phone and change the "Display pop-up windows while running in the background" of the printer driver app to "allow", then it worked perfectly!

I will keep the question and answer here in case someone encounters the same problem.

huangapple
  • 本文由 发表于 2020年8月23日 16:48:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/63545076.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定