3

I have been trying to convert Android WebView to PDF using PdfDocument. Below is the code:

Initialisation of WebView:

WebView webView = (WebView) findViewById(R.id.invoice_web_view);
WebSettings webSettings = webView.getSettings();
webSettings.setBuiltInZoomControls(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setDefaultTextEncodingName("UTF-8");

Converting to PDF:

private void createPdf(File file) {
    try {
        PdfDocument document = new PdfDocument();
        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(595, 842, 1).create(); //A4 page
        PdfDocument.Page page = document.startPage(pageInfo);

        View content = webView;
        content.draw(page.getCanvas());
        document.finishPage(page);
        document.writeTo(new FileOutputStream(file));
        document.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

The above code gives me this PDF. Below screenshot of PDF:

enter image description here

Now, when I change the WebView settings and add webSettings.setUseWideViewPort(true), it gives me below PDF with above code: enter image description here

I also use below code to print directly from Android device:

public void createWebPrintJob(WebView webView, Context context) {
    // Get a PrintManager instance
    PrintManager printManager = (PrintManager) context
            .getSystemService(Context.PRINT_SERVICE);

    // Get a print adapter instance
    PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter();

    // Create a print job with name and adapter instance
    String jobName = context.getString(R.string.app_name) + " Document";
    printManager.print(jobName, printAdapter,
            new PrintAttributes.Builder().build());
}

This code correctly renders the WebView and sends it to the printer. It gives below screen: enter image description here

I have a few questions:

  1. How do I alter createPdf() so that it gives me a PDF like in image 3?

  2. Image 3 still two pages whereas the PDF fits in one page. Do I need to modify my HTML code for this?

  3. Suppose my HTML is huge and it doesn't fit in one A4 page. Do I need to manually create separate pages using PdfDocument.Page and startPage() and finishPage()? How would I split the WebView based on page size? Is there any automatic way of creating pages?

varun
  • 465
  • 6
  • 23
  • did you try this , https://www.codeproject.com/Articles/989236/How-to-Convert-Android-View-to-PDF ? – Starlord Dec 29 '16 at 19:59
  • @Starlord I am not keen in using iText because they need you to buy a commercial license. I am sure there must be a way to utilise Android built-in PdfDocument to generate PDF. Android does that while printing the WebView. How can I achieve this? – varun Dec 30 '16 at 04:26
  • @varun Have you found out a solution for this problem? I'm having the same issue... – Rafael Jul 12 '17 at 11:59
  • Just found the solution, check out this answer: https://stackoverflow.com/a/43325705/5225620 – Rafael Jul 12 '17 at 13:04
  • @varun did you find answer of this question? – Rucha Bhatt Joshi Feb 27 '19 at 14:36

1 Answers1

0

I solved this by firstly converting the webview into a bitmap, then scaling the bitmap to fit into a single pdf page.

As for the printing part, I think it was more flexible to simply share the pdf and ask the user to select his printer software, as it's more useful than simply saving as pdf.

If you want to print several pages, I think it is more manageable to create different bitmaps and assign them to different pdf pages.

Here is the code to converting the webview into a single pdf page and then sharing it:

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