The latest version of Android, KitKat, adds long-awaited printing support to the platform. Android applications can now provide low-level control of print jobs, in addition to print integration for applications incorporating web content. This makes KitKat particularly well-suited to hybrid applications built with Xamarin using Razor templates.

Printing with a WebView
First let’s look at the easy to use print support offered through the WebView control.
Printing requires 3 steps:
- In an Activity, get a reference to the PrintManager system service.
- Create an instance of a class that inherits from PrintDocumentAdapter.
- Call the PrintManager‘s Print method, passing it the print adapter.
The PrintDocumentAdapter is an abstract class that provides a contract to implement for supplying print content. For web content, the WebView class includes a PrintDocumentAdapter, making printing HTML from a WebView incredibly easy to do:
The following example shows a WebView built using the Android WebView template, which uses Razor as an HTML templating engine:

Although printing can be done using any WebView, integrating printing with Razor and this project template makes it really easy to build a hybrid application that can leverage native features such as KitKat printing.
Printing from the WebView with C# is as simple as adding these 2 lines of code in the activity:
var printMgr = (PrintManager)GetSystemService(Context.PrintService);
printMgr.Print("Razor HMTL Hybrid", webView.CreatePrintDocumentAdapter(), null);
When we call Print Android presents a system dialog, allowing the user to choose the print destination, as shown below:

Custom Print Adapter
To print from native Android views, taking low-level control of the print layout, we can implement our own PrintDocumentAdapter.
For example, let’s say we would like to print the layout from the following screen:

In our implementation of PrintDocumentAdapter, the required methods to implement are:
- OnLayout – Allows laying out print content based on the PrintAttributes.
- OnWrite – Allows writing a PDF file with content to print.
In OnLayout, we create a PrintDocumentInfo instance, which contains metadata about the document being printed.
public override void OnLayout (PrintAttributes oldAttributes, PrintAttributes newAttributes,
CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras)
{
document = new PrintedPdfDocument (context, newAttributes);
CalculateScale (newAttributes);
var printInfo = new PrintDocumentInfo
.Builder ("MyPrint.pdf")
.SetContentType (PrintContentType.Document)
.SetPageCount (1)
.Build ();
callback.OnLayoutFinished (printInfo, true);
}
In OnWrite, we implement the code to draw printed content and write it to the output stream to be printed.
public override void OnWrite (PageRange[] pages, ParcelFileDescriptor destination,
CancellationSignal cancellationSignal, WriteResultCallback callback)
{
PrintedPdfDocument.Page page = document.StartPage (0);
page.Canvas.Scale (scale, scale);
view.Draw (page.Canvas);
document.FinishPage (page);
WritePrintedPdfDoc (destination);
document.Close ();
document.Dispose ();
callback.OnWriteFinished (pages);
}
Printing with our custom adapter is just like using the WebView‘s adapter. Simply pass an instance of the custom adapter, called GenericPrintAdapter in this case, to the PrintManager‘s Print method:
var printManager = (PrintManager)GetSystemService (Context.PrintService);
var content = FindViewById<LinearLayout> (Resource.Id.linearLayout1);
var printAdapter = new GenericPrintAdapter (this, content);
printManager.Print ("MyPrintJob", printAdapter, null);
When the user clicks print, the same system dialog is displayed. In addition to a local printer, you can select Google Cloud Print or print to a PDF file, resulting in the print shown below:

The printing support added to KitKat is a much welcome feature that is easy to get started with. You can download the code used in this post from my GitHub repo.