DImuthuUpe / AndroidPdfViewer

Android view for displaying PDFs rendered with PdfiumAndroid
Apache License 2.0
8.05k stars 1.85k forks source link

Android Print pdf lost signature/Seal 调用系统原生打印的时候印章/签名不显示 #1149

Closed lsCoding666 closed 1 year ago

lsCoding666 commented 1 year ago

My solution: Use pdfiumCore convert pdf to bitmap and combine bitmaps to PDF. pdf->pdfiumCore->images->pdf->print 用pdfiumCore 把每一页输出为 bitmap,然后再把 bitmap组合成 pdf 然后再打印 本来我认为使用pdfiumCore的情况下生成的 pdf应该会有印章,但是实际上并没有,所以这个方法没有奏效。还有什么办法能让打印时的 pdf带上印章吗? Originally, I thought that pdfs generated with pdfiumCore should have Seal, but they didn't, so this method didn't work. Is there any way to get the PDF stamped when printed?

    public static class MyPrintAdapter extends PrintDocumentAdapter {

        private Context context;
        private int pageHeight;
        private int pageWidth;
        private PdfDocument mPdfDocument;
        private int totalpages = 1;
        private String pdfPath;
        private List<Bitmap> mlist;

        public MyPrintAdapter(Context context, String pdfPath) {
            this.context = context;
            this.pdfPath = pdfPath;
        }

        @Override
        public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle metadata) {

            mPdfDocument = new PrintedPdfDocument(context, newAttributes); //创建可打印PDF文档对象

            pageHeight = newAttributes.getMediaSize().ISO_A4.getHeightMils() * 72 / 1000;  //设置尺寸
            pageWidth = newAttributes.getMediaSize().ISO_A4.getWidthMils() * 72 / 1000;

            if (cancellationSignal.isCanceled()) {
                callback.onLayoutCancelled();
                return;
            }

            ParcelFileDescriptor mFileDescriptor = null;
            PdfRenderer pdfRender = null;
            PdfRenderer.Page page = null;

            try {
                mlist = new ArrayList<>();
                ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.open(new File(pdfPath), ParcelFileDescriptor.MODE_READ_WRITE);
                com.shockwave.pdfium.PdfDocument pdf = pdfiumCore.newDocument(parcelFileDescriptor);
                pdfRender = new PdfRenderer(parcelFileDescriptor);
                totalpages = pdfRender.getPageCount();
                for (int pageNum = 0; pageNum < totalpages; pageNum++) {
//                    pdfiumCore.
                    pdfiumCore.openPage(pdf, pageNum);

                    int width = pdfiumCore.getPageWidth(pdf, pageNum);
                    int height = pdfiumCore.getPageHeight(pdf, pageNum);

                    Bitmap cbitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
                    pdfiumCore.renderPageBitmap(pdf, cbitmap, pageNum, 0, 0, width, height);

                    pdfiumCore.closeDocument(pdf);

                    new File(Environment.getExternalStorageDirectory() + "/PDF Reader").mkdirs();
                    File outputFile = new File(Environment.getExternalStorageDirectory() + "/PDF Reader", System.currentTimeMillis() + "jpg");
                    FileOutputStream outputStream = new FileOutputStream(outputFile);

                    cbitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream);
                    outputStream.close();
                    mlist.add(cbitmap);
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            if (totalpages > 0) {
                PrintDocumentInfo.Builder builder = new PrintDocumentInfo.Builder("快速入门.pdf").setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).setPageCount(totalpages);  //构建文档配置信息

                PrintDocumentInfo info = builder.build();
                callback.onLayoutFinished(info, true);
            } else {
                callback.onLayoutFailed("Page count is zero.");
            }
        }

        @Override
        public void onWrite(final PageRange[] pageRanges, final ParcelFileDescriptor destination, final CancellationSignal cancellationSignal, final WriteResultCallback callback) {
            for (int i = 0; i < totalpages; i++) {
                if (pageInRange(pageRanges, i)) //保证页码正确
                {
                    PdfDocument.PageInfo newPage = new PdfDocument.PageInfo.Builder(pageWidth, pageHeight, i).create();
                    PdfDocument.Page page = mPdfDocument.startPage(newPage);  //创建新页面

                    if (cancellationSignal.isCanceled()) {  //取消信号
                        callback.onWriteCancelled();
                        mPdfDocument.close();
                        mPdfDocument = null;
                        return;
                    }
                    drawPage(page, i);  //将内容绘制到页面Canvas上
                    mPdfDocument.finishPage(page);
                }
            }

            try {
                mPdfDocument.writeTo(new FileOutputStream(destination.getFileDescriptor()));
            } catch (IOException e) {
                callback.onWriteFailed(e.toString());
                return;
            } finally {
                mPdfDocument.close();
                mPdfDocument = null;
            }

            callback.onWriteFinished(pageRanges);
        }

        private boolean pageInRange(PageRange[] pageRanges, int page) {
            for (int i = 0; i < pageRanges.length; i++) {
                if ((page >= pageRanges[i].getStart()) && (page <= pageRanges[i].getEnd()))
                    return true;
            }
            return false;
        }

        //页面绘制(渲染)
        private void drawPage(PdfDocument.Page page, int pagenumber) {
            Canvas canvas = page.getCanvas();
            if (mlist != null) {
                Paint paint = new Paint();
                Bitmap bitmap = mlist.get(pagenumber);
                int bitmapWidth = bitmap.getWidth();
                int bitmapHeight = bitmap.getHeight();
                // 计算缩放比例
                float scale = (float) pageWidth / (float) bitmapWidth;
                // 取得想要缩放的matrix参数
                Matrix matrix = new Matrix();
                matrix.postScale(scale, scale);
                canvas.drawBitmap(bitmap, matrix, paint);
            }
        }

    }
lsCoding666 commented 1 year ago

Soloved int the onLayout method: change

pdfiumCore.renderPageBitmap(pdf, cbitmap, pageNum, 0, 0, width, height);

to

pdfiumCore.renderPageBitmap(pdf, cbitmap, pageNum, 0, 0, width, height,true);

full code

    public static void doPrint(File file) {
        if (file.exists() && file.isFile()) {
            //如果文件大小小于10kb 那么直接返回
            if (file.length() < 1024 * 10) {
                Toast.makeText(XUtil.getApplication().getApplicationContext(), "文件大小小于10kb 文件可能损坏", Toast.LENGTH_SHORT).show();
                return;
            }
            // Get a PrintManager instance 获取打印驱动对象
            PrintManager printManager = (PrintManager) ActivityUtil.getCurrentActivity().getSystemService(Context.PRINT_SERVICE);
            // Set job name, which will be displayed in the print queue 设置作业名称,该名称将显示在打印队列中
            String jobName = "深圳执法" + "文书";
            // Start a print job, passing in a PrintDocumentAdapter implementation
            // 启动打印作业,传入printdocumentadapter实现
            // to handle the generation of a print document处理打印文档的生成
            Toast.makeText(XUtil.getApplication().getApplicationContext(), "打印文件路径:" + file.getAbsolutePath(), Toast.LENGTH_SHORT).show();
            try {

                printManager.print(jobName, new MyPrintAdapter(ActivityUtil.getCurrentActivity(), file.getAbsolutePath()), new PrintAttributes.Builder().setMediaSize(PrintAttributes.MediaSize.ISO_A4).build());
            } catch (Exception e) {
                e.printStackTrace();
            }

        } else {
            Toast.makeText(XUtil.getApplication().getApplicationContext(), "文件不存在", Toast.LENGTH_SHORT).show();
            return;
        }
    }

    //使用PdfDocument打印 pdf

    /**
     * Created by guocheng on 2017/6/13.
     */
    public static class MyPrintAdapter extends PrintDocumentAdapter {

        private Context context;
        private int pageHeight;
        private int pageWidth;
        private PdfDocument mPdfDocument;
        private int totalpages = 1;
        private String pdfPath;
        private List<Bitmap> mlist;

        public MyPrintAdapter(Context context, String pdfPath) {
            this.context = context;
            this.pdfPath = pdfPath;
        }

        @Override
        public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle metadata) {

            mPdfDocument = new PrintedPdfDocument(context, newAttributes); //创建可打印PDF文档对象

            pageHeight = newAttributes.getMediaSize().ISO_A4.getHeightMils() * 72 / 1000;  //设置尺寸
            pageWidth = newAttributes.getMediaSize().ISO_A4.getWidthMils() * 72 / 1000;

            if (cancellationSignal.isCanceled()) {
                callback.onLayoutCancelled();
                return;
            }

            ParcelFileDescriptor mFileDescriptor = null;
            PdfRenderer pdfRender = null;
            PdfRenderer.Page page = null;
            PdfiumCore pdfiumCore = new PdfiumCore(context);

            try {
                mlist = new ArrayList<>();
                ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.open(new File(pdfPath), ParcelFileDescriptor.MODE_READ_WRITE);
                com.shockwave.pdfium.PdfDocument pdf = pdfiumCore.newDocument(parcelFileDescriptor);
                pdfRender = new PdfRenderer(parcelFileDescriptor);
                totalpages = pdfRender.getPageCount();
                for (int pageNum = 0; pageNum < totalpages; pageNum++) {
//                    pdfiumCore.
                    pdfiumCore.openPage(pdf, pageNum);

                    int width = pdfiumCore.getPageWidth(pdf, pageNum);
                    int height = pdfiumCore.getPageHeight(pdf, pageNum);

                    Bitmap cbitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
                    pdfiumCore.renderPageBitmap(pdf, cbitmap, pageNum, 0, 0, width, height,true);

                    pdfiumCore.closeDocument(pdf);

                    new File(Environment.getExternalStorageDirectory() + "/PDF Reader").mkdirs();
                    File outputFile = new File(Environment.getExternalStorageDirectory() + "/PDF Reader", System.currentTimeMillis() + "jpg");
                    FileOutputStream outputStream = new FileOutputStream(outputFile);

                    cbitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream);
                    outputStream.close();
                    mlist.add(cbitmap);
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            if (totalpages > 0) {
                PrintDocumentInfo.Builder builder = new PrintDocumentInfo.Builder("快速入门.pdf").setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).setPageCount(totalpages);  //构建文档配置信息

                PrintDocumentInfo info = builder.build();
                callback.onLayoutFinished(info, true);
            } else {
                callback.onLayoutFailed("Page count is zero.");
            }
        }

        @Override
        public void onWrite(final PageRange[] pageRanges, final ParcelFileDescriptor destination, final CancellationSignal cancellationSignal, final WriteResultCallback callback) {
            for (int i = 0; i < totalpages; i++) {
                if (pageInRange(pageRanges, i)) //保证页码正确
                {
                    PdfDocument.PageInfo newPage = new PdfDocument.PageInfo.Builder(pageWidth, pageHeight, i).create();
                    PdfDocument.Page page = mPdfDocument.startPage(newPage);  //创建新页面

                    if (cancellationSignal.isCanceled()) {  //取消信号
                        callback.onWriteCancelled();
                        mPdfDocument.close();
                        mPdfDocument = null;
                        return;
                    }
                    drawPage(page, i);  //将内容绘制到页面Canvas上
                    mPdfDocument.finishPage(page);
                }
            }

            try {
                mPdfDocument.writeTo(new FileOutputStream(destination.getFileDescriptor()));
            } catch (IOException e) {
                callback.onWriteFailed(e.toString());
                return;
            } finally {
                mPdfDocument.close();
                mPdfDocument = null;
            }

            callback.onWriteFinished(pageRanges);
        }

        private boolean pageInRange(PageRange[] pageRanges, int page) {
            for (int i = 0; i < pageRanges.length; i++) {
                if ((page >= pageRanges[i].getStart()) && (page <= pageRanges[i].getEnd()))
                    return true;
            }
            return false;
        }

        //页面绘制(渲染)
        private void drawPage(PdfDocument.Page page, int pagenumber) {
            Canvas canvas = page.getCanvas();
            if (mlist != null) {
                Paint paint = new Paint();
                Bitmap bitmap = mlist.get(pagenumber);
                int bitmapWidth = bitmap.getWidth();
                int bitmapHeight = bitmap.getHeight();
                // 计算缩放比例
                float scale = (float) pageWidth / (float) bitmapWidth;
                // 取得想要缩放的matrix参数
                Matrix matrix = new Matrix();
                matrix.postScale(scale, scale);
                canvas.drawBitmap(bitmap, matrix, paint);
            }
        }

    }