在安卓设备上从Webview创建PDF

7

我希望能够从Webview中创建PDF。目前,我可以从Webview中创建图片,但是我在将文档分成多个页面时遇到了一些问题。

首先,我从Webview中创建一个位图:

public static Bitmap screenShot(View view) {
        Bitmap bitmap = Bitmap.createBitmap(view.getWidth(),
                view.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        canvas.drawColor(Color.WHITE);
        view.draw(canvas);
        return bitmap;
    }

其次,我创建并展示PDF文档:

public void criaPdf(){
        Bitmap bitmap = Utils.screenShot(mContratoWebview);

        Document doc = new Document();


        File dir = new File(getFilesDir(), "app_imageDir");

        if(!dir.exists()) {
            dir.mkdirs();
        }

        File file = new File(dir, "contratoPdf.pdf");

        try {
            FileOutputStream fOut = new FileOutputStream(file);

            PdfWriter.getInstance(doc, fOut);

            //open the document
            doc.open();

            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);

            byte[] byteArray = stream.toByteArray();
            Image image = Image.getInstance(byteArray);
            image.scaleToFit(PageSize.A4.getHeight(), PageSize.A4.getWidth());

            doc.newPage();
            doc.add(image);
        } catch (DocumentException de) {
            Log.e("PDFCreator", "DocumentException:" + de);
        } catch (IOException e) {
            Log.e("PDFCreator", "ioException:" + e);
        }
        finally {
            doc.close();
        }

        mPdfView.fromFile(file)
                .pages(0, 1) // all pages are displayed by default
                .enableSwipe(true)
                .load();
        mPdfView.setVisibility(View.VISIBLE);
}

到目前为止,我得到了这个:

enter image description here

我的问题是:Webview的内容太大,无法适应PDF。我该怎么解决?


如何在Webview和PDF中显示图像? - Rucha Bhatt Joshi
你解决了这个问题吗?请分享。 - Ayush Sth
3个回答

8
WebView内置了生成PDF的功能,可以通过PrintManager服务使用。针对您的使用情况,我建议您编写/存储WebView的PrintAdapter的最终输出(即PDF文件)到本地文件并从那里继续操作。
这个链接将为您详细介绍实现细节。 http://www.annalytics.co.uk/android/pdf/2017/04/06/Save-PDF-From-An-Android-WebView/ 您可以通过小的调整实现与API级别19(KitKat)兼容的以上解决方案。
这应该可以解决您的问题,但如果您在实施中遇到任何问题,请告诉我。

1
我正在尝试您在链接http://www.annalytics.co.uk/android/pdf/2017/04/06/Save-PDF-From-An-Android-WebView/中提到的代码,但是当我创建PdfPrint类时,它会出现错误,即PrintDocumentAdapter.WriteResultCallback不是公共的,无法从包外访问。 - Ahesanali Suthar
1
我必须创建android.print包。 - Ahesanali Suthar
嗨,@AhesanaliMomin,你能否提供一下你遇到的问题的更多细节呢?我建议你创建一个新问题,详细描述你的问题并附上代码,并在这里发布该问题的链接。 - Rakesh Gopathi
@RakeshGopathi,您能解释一下实现API 19兼容性所需的“小调整”是什么吗? - suomi35
您可以通过使用if语句来检查API版本,从WebView中创建PrintAdpter,如下所示:__________ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { printAdapter = webView.createPrintDocumentAdapter(jobName); } else { printAdapter = webView.createPrintDocumentAdapter(); } - Rakesh Gopathi
显示剩余14条评论

5

要从Webview创建PDF,您需要Android>KitKat -> SDK>=19。

  btnSave.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {

                createWebPrintJob(webView);
            } else {



            }

        }
    });

//// 函数:

private void createWebPrintJob(WebView webView) {

    PrintManager printManager = (PrintManager) this
            .getSystemService(Context.PRINT_SERVICE);

    PrintDocumentAdapter printAdapter =
            webView.createPrintDocumentAdapter();

    String jobName = getString(R.string.app_name) + " Print Test";

    if (printManager != null) {
        printManager.print(jobName, printAdapter,
                new PrintAttributes.Builder().build());
    }
}

我在创建Webview图片时遇到了问题:))))

你找到任何解决方案可以在WebView和PDF中显示图像吗? - Rucha Bhatt Joshi
1
你能分享一下你的代码或者帮我在这里 https://stackoverflow.com/questions/54870164/convert-html-into-pdf-using-webview-not-display-full-content-with-images 上如何实现吗? - Rucha Bhatt Joshi

0
在我的情况下,我通过首先将Webview转换为位图,然后将位图缩放以适应PDF页面来解决了这个问题。
至于打印部分,我认为更灵活的做法是直接共享PDF并要求用户选择打印机软件,因为这比仅保存为PDF更有用。
如果您想打印多个页面,我认为更容易管理的方法是创建不同的位图并将它们分配给不同的PDF页面。
以下是将Webview转换为单个PDF页面并共享的代码:
public static void sharePdfFile(WebView webView, Context context)
{
    Bitmap bitmap = webviewToBitmap( webView );
    PrintedPdfDocument pdf =  bitmapToPdf( bitmap, context );
    File file = pdfToFile( pdf, context );
    shareFile( file,"application/pdf", context );
}

private static void shareFile(File file, String contentType, Context context)
{
    Uri uri = FileProvider.getUriForFile(
        context,
        context.getPackageName() + ".fileprovider",
        file);
    Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
    shareIntent.setType(contentType);
    shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
    shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    Toast.makeText(
        context,
        "Choose your printer app",
        Toast.LENGTH_LONG
    ).show();
    context.startActivity( shareIntent );
}

private static File pdfToFile(PrintedPdfDocument printedPdfDocument, Context context)
{
    File file = new File(context.getFilesDir(), "share.pdf");
    try {
        FileOutputStream outputStream = new FileOutputStream(file);
        printedPdfDocument.writeTo(outputStream);
        outputStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    printedPdfDocument.close();
    return file;
}


private static PrintedPdfDocument bitmapToPdf(Bitmap bitmap, Context context)
{
    PrintAttributes printAttributes = new PrintAttributes.Builder()
        .setColorMode(PrintAttributes.COLOR_MODE_COLOR)
        .setMediaSize(PrintAttributes.MediaSize.ISO_A4)
        .setMinMargins(PrintAttributes.Margins.NO_MARGINS)
        .setResolution(new PrintAttributes.Resolution("1", "label", 300, 300))
        .build();
    PrintedPdfDocument printedPdfDocument = new PrintedPdfDocument(context, printAttributes);
    PdfDocument.Page pdfDocumentPage = printedPdfDocument.startPage(1);
    Canvas pdfCanvas = pdfDocumentPage.getCanvas();
    bitmap = scaleBitmapToHeight(bitmap, pdfCanvas.getHeight());
    pdfCanvas.drawBitmap(bitmap, 0f, 0f, null);
    printedPdfDocument.finishPage(pdfDocumentPage);
    return printedPdfDocument;
}

private static Bitmap webviewToBitmap(WebView webView) {
    webView.measure(
        View.MeasureSpec.makeMeasureSpec(
            0,
            View.MeasureSpec.UNSPECIFIED
        ),
        View.MeasureSpec.makeMeasureSpec(
            0,
            View.MeasureSpec.UNSPECIFIED
        )
    );
    int webViewWidth = webView.getMeasuredWidth();
    int webViewHeight = webView.getMeasuredHeight();
    webView.layout(0,0, webViewWidth, webViewHeight );
    Bitmap bitmap = Bitmap.createBitmap(webViewWidth, webViewHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    canvas.drawBitmap(bitmap, 0, bitmap.getHeight(), new Paint());
    webView.draw(canvas);
    return bitmap;
}

private static Bitmap scaleBitmapToHeight(Bitmap bitmap, int maxHeight) {
    int height = bitmap.getHeight();
    if(height > maxHeight) {
        int width = bitmap.getWidth();
        float scalePercentage = ((float)maxHeight) / height;
        return Bitmap.createScaledBitmap(bitmap, (int) (width * scalePercentage), maxHeight, false);
    }
    return bitmap;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接