Cómo imprimir documentos HTML

En Android, para imprimir contenido más allá de una simple foto, es necesario redactar texto y gráficos en un documento impreso. El framework de Android proporciona una forma de usar HTML para redactar un documento e imprimirlo con un mínimo de código.

En Android 4.4 (API nivel 19), se actualizó la clase WebView a fin de permitir la impresión de contenido HTML. La clase te permite cargar un recurso HTML local o descargar una página de la Web, crear un trabajo de impresión y entregarlo a los servicios de impresión de Android.

En esta lección, se muestra cómo crear rápidamente un documento HTML que contenga texto y gráficos, y usar WebView para imprimirlo.

Cómo cargar un documento HTML

Imprimir un documento HTML con WebView implica cargar un recurso HTML o crear un documento HTML como una cadena. En esta sección, se describe cómo compilar una cadena HTML y cargarla en un WebView para imprimir.

Este objeto de vista generalmente se usa como parte de un diseño de actividad. Sin embargo, si tu aplicación no usa un WebView, puedes crear una instancia de la clase específicamente para fines de impresión. Los pasos principales para crear esta vista de impresión personalizada son los siguientes:

  1. Crea un WebViewClient que inicie un trabajo de impresión después de cargar el recurso HTML.
  2. Carga el recurso HTML en el objeto WebView.

En la siguiente muestra de código, se muestra cómo crear un objeto WebViewClient simple y cargar un documento HTML sobre la marcha:

Kotlin

private var mWebView: WebView? = null

private fun doWebViewPrint() {
    // Create a WebView object specifically for printing
    val webView = WebView(activity)
    webView.webViewClient = object : WebViewClient() {

        override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest) = false

        override fun onPageFinished(view: WebView, url: String) {
            Log.i(TAG, "page finished loading $url")
            createWebPrintJob(view)
            mWebView = null
        }
    }

    // Generate an HTML document on the fly:
    val htmlDocument =
            "<html><body><h1>Test Content</h1><p>Testing, testing, testing...</p></body></html>"
    webView.loadDataWithBaseURL(null, htmlDocument, "text/HTML", "UTF-8", null)

    // Keep a reference to WebView object until you pass the PrintDocumentAdapter
    // to the PrintManager
    mWebView = webView
}

Java

private WebView mWebView;

private void doWebViewPrint() {
    // Create a WebView object specifically for printing
    WebView webView = new WebView(getActivity());
    webView.setWebViewClient(new WebViewClient() {

            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                return false;
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                Log.i(TAG, "page finished loading " + url);
                createWebPrintJob(view);
                mWebView = null;
            }
    });

    // Generate an HTML document on the fly:
    String htmlDocument = "<html><body><h1>Test Content</h1><p>Testing, " +
            "testing, testing...</p></body></html>";
    webView.loadDataWithBaseURL(null, htmlDocument, "text/HTML", "UTF-8", null);

    // Keep a reference to WebView object until you pass the PrintDocumentAdapter
    // to the PrintManager
    mWebView = webView;
}

Nota: Asegúrate de que la llamada para generar un trabajo de impresión se realice en el método onPageFinished() de la WebViewClient que creaste en la sección anterior. Si no esperas hasta que finalice la carga de la página, es posible que la salida de impresión esté incompleta o en blanco, o que falle por completo.

Nota: En el código de ejemplo anterior, se incluye una instancia del objeto WebView para que no se recolecte como elemento no utilizado antes de la creación del trabajo de impresión. Asegúrate de hacer lo mismo en tu propia implementación; de lo contrario, el proceso de impresión podría fallar.

Si deseas incluir gráficos en la página, coloca los archivos gráficos en el directorio assets/ de tu proyecto y especifica una URL base en el primer parámetro del método loadDataWithBaseURL(), como se muestra en el siguiente ejemplo de código:

Kotlin

webView.loadDataWithBaseURL(
        "file:///android_asset/images/",
        htmlBody,
        "text/HTML",
        "UTF-8",
        null
)

Java

webView.loadDataWithBaseURL("file:///android_asset/images/", htmlBody,
        "text/HTML", "UTF-8", null);

También puedes reemplazar el método loadDataWithBaseURL() por loadUrl() para cargar una página web a fin de imprimir, como se muestra a continuación.

Kotlin

webView.loadUrl("https://developer.android.com/about/index.html")

Java

// Print an existing web page (remember to request INTERNET permission!):
webView.loadUrl("https://developer.android.com/about/index.html");

Cuando uses WebView para crear documentos impresos, debes tener en cuenta las siguientes limitaciones:

  • No puedes agregar encabezados o pies de página, incluidos los números de página, al documento.
  • Las opciones de impresión del documento HTML no incluyen la posibilidad de imprimir rangos de página; por ejemplo, no se admite imprimir las páginas 2 a 4 de un documento HTML de 10 páginas.
  • Una instancia de WebView solo puede procesar un trabajo de impresión por vez.
  • No se admiten documentos HTML que contengan atributos de impresión CSS, como las propiedades de modo horizontal.
  • No puedes usar JavaScript en un documento HTML para activar la impresión.

Nota: El contenido de un objeto WebView que se incluye en un diseño también se puede imprimir una vez que carga un documento.

Si quieres crear una salida de impresión más personalizada y tener control total sobre el contenido dibujado en la página impresa, ve a la siguiente lección: Cómo imprimir un documento personalizado.

Después de crear un objeto WebView y cargar tu contenido HTML, tu aplicación casi finalizó con su parte del proceso de impresión. Los siguientes pasos son acceder a PrintManager, crear un adaptador de impresión y, por último, crear un trabajo de impresión. En el siguiente ejemplo, se muestra cómo realizar estos pasos:

Kotlin

private fun createWebPrintJob(webView: WebView) {

    // Get a PrintManager instance
    (activity?.getSystemService(Context.PRINT_SERVICE) as? PrintManager)?.let { printManager ->

        val jobName = "${getString(R.string.app_name)} Document"

        // Get a print adapter instance
        val printAdapter = webView.createPrintDocumentAdapter(jobName)

        // Create a print job with name and adapter instance
        printManager.print(
                jobName,
                printAdapter,
                PrintAttributes.Builder().build()
        ).also { printJob ->

            // Save the job object for later status checking
            printJobs += printJob
        }
    }
}

Java

private void createWebPrintJob(WebView webView) {

    // Get a PrintManager instance
    PrintManager printManager = (PrintManager) getActivity()
            .getSystemService(Context.PRINT_SERVICE);

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

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

    // Create a print job with name and adapter instance
    PrintJob printJob = printManager.print(jobName, printAdapter,
            new PrintAttributes.Builder().build());

    // Save the job object for later status checking
    printJobs.add(printJob);
}

En este ejemplo, se guarda una instancia del objeto PrintJob para que la use la aplicación, lo cual no es necesario. Tu aplicación puede usar este objeto para realizar un seguimiento del progreso del trabajo de impresión mientras se procesa. Este enfoque es útil cuando deseas supervisar el estado del trabajo de impresión en tu solicitud para determinar si se completa, falla o cancela el usuario. No es necesario crear una notificación desde la app, ya que el marco de trabajo de impresión crea automáticamente una notificación del sistema para el trabajo de impresión.