1

我有以下代码用于使用 Android 打印框架打印 PDF 文件:

这是我的 PrintDocumentAdapter 类:

@TargetApi(Build.VERSION_CODES.KITKAT)
public class PrintPDFAdapter extends PrintDocumentAdapter {
    private File pdfFile;
    private String fileName;

    public PrintPDFAdapter(File pdfFile, String fileName) {
        this.pdfFile = pdfFile;
        this.fileName = fileName;
    }


    @Override
    public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras) {
        if (cancellationSignal.isCanceled()) {
            callback.onLayoutCancelled();
            return;
        }

        PrintDocumentInfo pdi = new PrintDocumentInfo.Builder(fileName).setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build();

        callback.onLayoutFinished(pdi, true);
    }

    @Override
    public void onWrite(PageRange[] pages, ParcelFileDescriptor destination, CancellationSignal cancellationSignal, WriteResultCallback callback) {
        InputStream input = null;
        OutputStream output = null;

        try {

            input = new FileInputStream(pdfFile);
            output = new FileOutputStream(destination.getFileDescriptor());

            byte[] buf = new byte[1024];
            int bytesRead;

                while ((bytesRead = input.read(buf)) > 0) {
                output.write(buf, 0, bytesRead);
            }

            callback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES});

        } catch (FileNotFoundException ee){
            //Catch exception
        } catch (Exception e) {
            //Catch exception
        } finally {
            try {
                input.close();
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

这是我调用 PrintManager 打印命令的方法:

@TargetApi(Build.VERSION_CODES.KITKAT)
private void doPDFPrint(File pdfFile, String filename) {
    PrintManager printManager = (PrintManager) this.getSystemService(Context.PRINT_SERVICE);
    String jobName = this.getString(R.string.app_name) + " Report";
    PrintPDFAdapter pda = new PrintPDFAdapter(pdfFile, filename);
    PrintAttributes attrib = new PrintAttributes.Builder().
            setMediaSize(PrintAttributes.MediaSize.NA_LETTER.asLandscape()).
            setMinMargins(PrintAttributes.Margins.NO_MARGINS).
            build();
    printManager.print(jobName, pda, attrib);
}

我要打印的 PDF 是横向的。出于某种原因,当发送它进行打印时,PDF 文件会横向旋转并被剪裁。我想知道,有什么办法可以解决这个问题吗?

更新:我刚刚做了一个测试打印,它实际上打印正确。但是,预览显示它横向旋转。

4

1 回答 1

0

就我而言,这是因为我使用自己的转换,并且在提供转换时,本机渲染器不会应用 PDF 页面属性中指定的页面旋转。目前无法通过 Android API 获取此属性,因此我使用了 iText:

private PdfReader _iTextReader;

...

_iTextReader = new PdfReader(file.getAbsolutePath());

...

// iText uses 1-indexed pages
PdfDictionary iTextPage = _iTextReader.getPageN(pageNumber + 1);
PdfNumber rotate = iTextPage.getAsNumber(PdfName.ROTATE);
if (rotate != null && rotate.intValue() % 360 != 0) {
   // getPageSize returns media box
   float mediaBoxWidth = _iTextReader.getPageSize(pageNumber + 1).getWidth();
   float mediaBoxHeight = _iTextReader.getPageSize(pageNumber + 1).getHeight();
   float iTextCenterX = mediaBoxWidth / 2;
   float iTextCenterY = mediaBoxHeight / 2;
   Util.Log("Applying " + rotate.intValue() + " degree rotation per PDF page attributes.");
   pdfMatrix.postRotate(rotate.intValue(), iTextCenterX, iTextCenterY);
   /*
    * Transform it back to the top-left corner.
    * For the life of me, I do not know why these translations are right. But I've
    * test both portrait->landscape and landscape->portrait on all rotation angles.
    */
   if (rotate.intValue() == 90) {
      pdfMatrix.postTranslate(iTextCenterX - iTextCenterY, iTextCenterX - iTextCenterY);
   } else if (rotate.intValue() == 270) {
      pdfMatrix.postTranslate(3 * iTextCenterY - 3 * iTextCenterX, iTextCenterX - iTextCenterY);
   }
}

这是原生 PDF 渲染器源代码的链接:https ://github.com/android/platform_frameworks_base/blob/master/core/jni/android/graphics/pdf/PdfRenderer.cpp

于 2017-01-02T04:04:04.750 回答