Android Printing Framework is used to print content from within Android applications. While subsequent chapters will explore in more detail the options for adding printing support to your applications, this chapter will focus on the various printing options now available in Android and the steps involved in enabling those options.
The chapter will then provide an overview of the various printing features available to Android developers to build printing support into applications.
The Android Printing Architecture
The Printing framework provides printing in Android. In basic terms, this framework consists of a Print Manager and a number of print service plugins.
It is the responsibility of the Print Manager to handle the print requests from applications on the device and to interact with the print service plugins installed on the device, thereby ensuring that print requests are fulfilled.
By default, many Android devices have print service plugins installed to enable printing using the Google Cloud Print and Google Drive services. Print Services Plugins for other printer types, if not already installed, may also be obtained from the Google Play store.
Print Service Plugins are currently available for HP, Epson, Samsung, and Canon printers, and plugins from other printer manufacturers will most likely be released in the future. However, the Google Cloud Print service plugin can print from Android to just about any printer type and model. This book will use the HP Print Services Plugin as a reference example.
The Print Service Plugins
The purpose of the Print Service plugins is to enable applications to print to compatible printers that are visible to the Android device via a local area wireless network or Bluetooth.
The presence of the Print Service Plugin on an Android device can be verified by loading the Google Play app and performing a search for “Print Service Plugin”.
Once the plugin is listed in the Play Store, and if it is not already installed, it can be installed by selecting the Install button. Figure 80-1, for example, shows the HP Print Service plugin within Google Play.
The Print Services plugins will automatically detect compatible printers on the network to which the Android device is currently connected and list them as options when printing from an application.
Google Cloud Print
Google Cloud Print is a service provided by Google that enables you to print content onto your printer over the web from anywhere with internet connectivity. Google Cloud Print supports many devices and printer models in both Cloud Ready and Classic printers. A Cloud Ready printer has technology built-in that enables printing via the web. Manufacturers that provide cloud-ready printers include Brother, Canon, Dell, Epson, HP, Kodak, and Samsung. To identify if your printer is both cloud-ready and supported by Google Cloud Print, review the list of printers at the following URL:
https://www.google.com/cloudprint/learn/printers.html
In the case of classic, non-Cloud Ready printers, Google Cloud Print provides support for cloud printing by installing software on the computer system to which the classic printer is connected (either directly or over a home or office network).
To set up Google Cloud Print, visit the following web page and log in using the same Google account ID that you use when logging in to your Android devices:
https://www.google.com/cloudprint/learn/index.html
Once printers have been added to your Google Cloud Print account, they will be listed as printer destination options when you print from within Android applications.
Printing to Google Drive
In addition to supporting physical printers, it is also possible to save printed output to your Google Drive account. When printing from a device, select the Save to Google Drive option in the printing panel. The content to be printed will then be converted to a PDF file and saved to the Google Drive cloud-based storage associated with the currently active Google Account ID on the device.
Save as PDF
The final printing option provided by Android allows the printed content to be saved locally as a PDF file on the Android device. Once selected, this option will request a name for the PDF file and a location on the device to which the document will be saved.
Both the Save as PDF and Google Drive options can be invaluable in terms of saving paper when testing the printing functionality of your own Android applications.
Printing from Android Devices
Google recommends that applications that can print content do so by placing the print option in the Overflow menu. Many applications bundled with Android now include “Print…” menu options. Figure 80-2, for example, shows the Print option accessed by selecting the “Share…” option in the Overflow menu of the Chrome browser application:
Once the print option has been selected from within an application, the standard Android print screen will appear, showing a preview of the content to be printed, as illustrated in Figure 80-3:
Tapping the panel along the top of the screen will display the full range of printing options:
The Android print panel provides standard printing options, such as paper size, color, orientation, and number of copies. Other print destination options may be accessed by tapping on the current printer or PDF output selection.
Options for Building Print Support into Android Apps
The Printing framework provides several options for incorporating print support into Android applications. These options can be categorized as follows:
Image Printing
As the name suggests, this option allows image printing to be incorporated into Android applications. When adding this feature to an application, the first step is to create a new instance of the PrintHelper class:
val imagePrinter = PrintHelper(context)
Code language: Kotlin (kotlin)
Next, the scale mode for the printed image may be specified via a call to the setScaleMode() method of the PrintHelper instance. Options are as follows:
- SCALE_MODE_FIT – The image will be scaled to fit within the paper size without cropping or changes to the aspect ratio. This will typically result in white space appearing in one dimension.
- SCALE_MODE_FILL – The image will be scaled to fill the paper size with cropping performed where necessary to avoid the appearance of white space in the printed output.
Without a scale mode setting, the system will default to SCALE_MODE_FILL. The following code, for example, sets scale to fit mode on the previously declared PrintHelper instance:
imagePrinter.setScaleMode(PrintHelper.SCALE_MODE_FIT)
Code language: Kotlin (kotlin)
Similarly, the color mode may also be configured to indicate whether the print output is to be in color or black and white. This is achieved by passing one of the following options through to the setColorMode() method of the PrintHelper instance:
- COLOR_MODE_COLOR – Indicates that the image is to be printed in color.
- COLOR_MODE_MONOCHROME – Indicates that the image will be printed in black and white.
The printing framework will default to color printing unless the monochrome option is specified as follows:
imagePrinter.colorMode = PrintHelper.COLOR_MODE_MONOCHROME
Code language: Kotlin (kotlin)
All that is required to complete the printing operation is an image to be printed and a call to the printBitmap() method of the PrintHelper instance, passing through a string representing the name to be assigned to the print job and a reference to the image (in the form of either a Bitmap object or a Uri reference to the image):
val bitmap = BitmapFactory.decodeResource(resources,
R.drawable.oceanscene)
imagePrinter.printBitmap("My Test Print Job", bitmap)
Code language: Kotlin (kotlin)
Once the print job has been started, the Printing framework will display the print dialog and handle both the subsequent interaction with the user and the printing of the image on the user-selected print destination.
Creating and Printing HTML Content
The Android Printing framework also provides an easy way to print HTML-based content within an application. This content can either be HTML content referenced by the URL of a page hosted on a website or HTML content dynamically created within the application.
To enable HTML printing, the WebView class has been extended to include support for printing with minimal coding requirements.
When dynamically creating HTML content (as opposed to loading and printing an existing web page), the process involves the creation of a WebView object and associating with it a WebViewClient instance. The web view client is then configured to start a print job when the HTML has finished being loaded into the WebView.
With the web view client configured, the HTML is loaded into the WebView, and the print process is triggered. Consider, for example, the following code:
private fun printWebView() {
val webView = WebView(this)
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView,
request: WebResourceRequest): Boolean {
return false
}
override fun onPageFinished(view: WebView, url: String) {
createWebPrintJob(view)
myWebView = null
}
}
val htmlDocument = "<html><body><h1>Android Print Test</h1><p>" +
"This is some sample content.</p></body></html>"
webView.loadDataWithBaseURL(null, htmlDocument,
"text/HTML", "UTF-8", null)
myWebView = webView
}
Code language: Kotlin (kotlin)
The code in this method begins by declaring a variable named myWebView in which will be stored a reference to the WebView instance created in the method. Within the printContent() method, an instance of the WebView class is created to which a WebViewClient instance is assigned.
The WebViewClient assigned to the web view object is configured to indicate that the loading of the HTML content is to be handled by the WebView instance (by returning false from the shouldOverrideUrlLoading()) method. More importantly, an onPageFinished() handler method is declared and implemented to call the createWebPrintJob() method. The onPageFinished() callback method will be called automatically when all HTML content is loaded into the web view. This ensures that the print job is not started until the content is ready, ensuring that all content is printed.
Next, a string is created containing some HTML to serve as the content. This is then loaded into the web view. Once the HTML is loaded, the onPageFinished() method will trigger. Finally, the method stores a reference to the web view object. Without this vital step, there is a significant risk that the Java runtime system will assume that the application no longer needs the web view object and will discard it to free up memory (a concept referred to in Java terminology as garbage collection), resulting in the print job terminating before completion. All that remains in this example is to implement the createWebPrintJob() method as follows:
private fun createWebPrintJob(webView: WebView) {
val printManager = this
.getSystemService(Context.PRINT_SERVICE) as PrintManager
val printAdapter = webView.createPrintDocumentAdapter("MyDocument")
val jobName = getString(R.string.app_name) + " Document"
printManager.print(jobName, printAdapter,
PrintAttributes.Builder().build())
}
Code language: Kotlin (kotlin)
This method obtains a reference to the PrintManager service and instructs the web view instance to create a print adapter. A new string is created to store the name of the print job (which, in this case, is based on the name of the application and the word “Document”).
Finally, the print job is started by calling the print() method of the print manager, passing through the job name, print adapter, and a set of default print attributes. If required, the print attributes could be customized to specify resolution (dots per inch), margin, and color options.
Printing a Web Page
The steps involved in printing a web page are similar to those outlined above, with the exception that the web view is passed the URL of the web page to be printed in place of the dynamically created HTML, for example:
myWebView?.loadUrl("https://developer.android.com/google/index.html")
Code language: Kotlin (kotlin)
It is also important to note that the WebViewClient configuration is only necessary if a web page is to automatically print as soon as it has loaded. If the printing is to be initiated by the user selecting a menu option after the page has loaded, only the code in the createWebPrintJob() method outlined above needs to be included in the application code. The next chapter, An Android Studio HTML and Web Printing Example, will demonstrate such a scenario.
Printing a Custom Document
While the HTML and web printing features introduced by the Printing framework provide an easy path to printing content from within an Android application, it is clear that these options will be overly simplistic for more advanced printing requirements. The Printing framework also provides custom document printing support for more complex printing tasks. This allows content in the form of text and graphics to be drawn onto a canvas and then printed.
Unlike HTML and image printing, which can be implemented with relative ease, custom document printing is a more complex, multi-stage process which will be outlined in the An Android Studio Custom Printing Tutorial chapter of this book. These steps can be summarized as follows:
- Connect to the Android Print Manager
- Create a Custom Print Adapter sub-classed from the PrintDocumentAdapter class
- Create a PdfDocument instance to represent the document pages
- Obtain a reference to the pages of the PdfDocument instance, each of which has associated with it a Canvas instance
- Draw the content on the page canvases
- Notify the print framework that the document is ready to print
The custom print adapter outlined in the above steps must implement several methods that the Android system will call upon to perform specific tasks during printing. The most important of these are the onLayout() method, responsible for re-arranging the document layout in response to the user changing settings such as paper size or page orientation, and the onWrite() method which is responsible for rendering the pages to be printed. The chapter entitled An Android Studio Custom Printing Tutorial will cover this topic in detail.
Summary
The Android SDK can print content from within a running app. Print output can be directed to suitably configured printers, a local PDF file, or to the cloud via Google Drive. From the perspective of the Android application developer, these capabilities are available for use in applications by making use of the Printing framework. By far, the easiest printing options to implement are those involving content in the form of images and HTML. More advanced printing may, however, be implemented using the custom document printing features of the framework.