I've been having troubles getting PDF printing work on Android. What I'm trying to do is render some HTML in WebView, then draw the WebView contents on a PDF canvas and finally write the PDF to a file. The problem I'm having is that when I draw to the PDF canvas the content gets clipped even though there is plenty of canvas left. I've tried resizing the canvas using the .clipRect(Rect rect, Op op)
and that kind of worked but not as well as I would've liked.
I also have no idea how I can translate the HTML px measurements to the PDF PostScript 1/72th inch measurements reliably.
Here's the code I'm using:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
WebView wv = (WebView) this.findViewById(R.id.webView1);
wv.loadUrl("file:///android_asset/temp.html");
}
public void button1onClick(View v)
{
//Create PDF document
PdfDocument doc = new PdfDocument();
//Create A4 sized PDF page
PageInfo pageInfo = new PageInfo.Builder(595,842,1).create();
Page page = doc.startPage(pageInfo);
WebView wv = (WebView) this.findViewById(R.id.webView1);
page.getCanvas().setDensity(200);
//Draw the webview to the canvas
wv.draw(page.getCanvas());
doc.finishPage(page);
try
{
//Create the PDF file
File root = Environment.getExternalStorageDirectory();
File file = new File(root,"webview.pdf");
FileOutputStream out = new FileOutputStream(file);
doc.writeTo(out);
out.close();
doc.close();
//Open the PDF
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
}
catch(Exception e)
{
throw new RuntimeException("Error generating file", e);
}
}
Basically the program just loads the temp.html file to webview and renders me a button that I can use to create the PDF.
The temp.html file looks like:
<html>
<head>
<style>
div.border
{
width:600px;
height:800px;
border:1px solid black;
}
</style>
</head>
<body>
<div class="border"></div>
</body>
And here is the result with manually added black border to show the scale:
I would really appreciate some tips on how to convert HTML to PDF reliably on Android without using libraries that require licenses for commercial use.
Opening a PDF file in Android using WebView All you need to do is just put WebView in your layout and load the desired URL by using the webView. loadUrl() function. Now, run the application on your mobile phone and the PDF will be displayed on the screen.
The parameter to onDraw() is a Canvas object that the view can use to draw itself. The Canvas class defines methods for drawing text, lines, bitmaps, and many other graphics primitives. You can use these methods in onDraw() to create your custom user interface (UI).
Summary: Don't modify the density, (it should be set on your device, probably to medium 160 dpi) instead, use scale. If you Just need Bitmaps of your HTML page in your PDF (No hyper-link function), this works. This is what your code is generating, with the following code:
//Create PDF document
PdfDocument doc = new PdfDocument();
//Create A4 sized PDF page
int my_width = 595;
int my_height = 842;
PageInfo pageInfo = new PageInfo.Builder(my_width,my_height,1).create();
// PageInfo pageInfo = new PageInfo.Builder(650,850,1).create();
Page page = doc.startPage(pageInfo);
WebView wv = (WebView) this.findViewById(R.id.webView1);
Canvas canvas = page.getCanvas();
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
final DisplayMetrics displayMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels;
float density = displayMetrics.density;
int wvWidth = wv.getWidth();
int wvHeight= wv.getHeight();
float wvScaleX= wv.getScaleX();
float wvScaleY= wv.getScaleY();
// canvas.setDensity(100);//200 Bitmap.DENSITY_NONE
int cdensity = canvas.getDensity();
float scaleWidth = (float)width/(float)my_width;
float scaleHeight = (float)height/(float)my_height;
canvas.scale(scaleWidth, scaleHeight);
Log.e("button1onClick","canvas width:" + canvas.getHeight() + " canvas height:" + canvas.getWidth());
Log.e("button1onClick","metrics width:" + width + " metrics height:" + height + "metrics density:" + density);
Log.e("button1onClick"," wvWidth:" + wvWidth + " wvHeight:" + wvHeight);
Log.e("button1onClick"," scaleWidth: " + scaleWidth +
" scaleHeight:" + scaleHeight +" cdensity:" + cdensity);
Paint paint = new Paint();
// paint.setStyle(Style.FILL);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1);
//Draw the webview to the canvas
wv.draw(canvas);
canvas.scale(1f, 1f);
canvas.drawRect(0, 0, canvas.getWidth()-1, canvas.getHeight()-1, paint);
canvas.drawText("Direct drawn Red Rectangle to fill page canvas 0, 0," +
canvas.getWidth() + "," + canvas.getHeight(), 100, 100, paint);
doc.finishPage(page);
This works well (Hyper-links cannot work of course). More complex example:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With