Ya está disponible la segunda Vista previa para desarrolladores de Android 11; pruébala y comparte tus comentarios.

Cómo imprimir documentos HTML

En Android, si quieres imprimir contenido que no sea una simple foto, es necesario redactar texto y gráficos en un documento impreso. El marco de trabajo de Android ofrece una forma de usar HTML para componer un documento y luego imprimirlo con un mínimo de código.

En Android 4.4 (API nivel 19), la clase WebView se actualizó para 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 string. En esta sección, se describe cómo compilar una cadena HTML y cargarla en un objeto 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 está utilizando un objeto 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 objeto 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 el siguiente código de ejemplo, se muestra cómo crear un objeto WebViewClient simple y cargar un documento HTML creado 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() del objeto WebViewClient que creaste en la sección anterior. Si no esperas hasta que finalice la carga de la página, la salida de impresión puede estar incompleta o en blanco, o puede fallar por completo.

Nota: En el código de ejemplo anterior, hay una instancia del objeto WebView a fin de 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 quieres 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 cargar una página web para imprimirla mediante la sustitución del método loadDataWithBaseURL() con loadUrl() como se muestra a continuación.

Kotlin

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

Java

    // Print an existing web page (remember to request INTERNET permission!):
    webView.loadUrl("http://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 de documentos HTML no incluyen la capacidad de imprimir rangos de página; por ejemplo, no es posible 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 el 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 uso de la aplicación, lo cual no es necesario. Tu aplicación puede utilizar este objeto para realizar un seguimiento del progreso del trabajo de impresión mientras se está procesando. Este enfoque resulta útil cuando deseas monitorear el estado del trabajo de impresión en tu aplicación para comprobar si se completa, falla o lo cancela el usuario. No es necesario crear una notificación en la app, porque el marco de impresión crea automáticamente una notificación del sistema para el trabajo de impresión.