Como imprimir documentos HTML

Para imprimir conteúdo além de uma foto simples no Android, é necessário escrever texto e gráficos em um documento de impressão. O framework do Android oferece uma maneira de usar HTML para compor um documento e imprimi-lo com um mínimo de código.

No Android 4.4 (API de nível 19), a classe WebView foi atualizada para permitir a impressão de conteúdo HTML. A classe permite que você carregue um recurso HTML local ou faça o download de uma página da Web, crie um trabalho de impressão e o entregue aos serviços de impressão do Android.

Esta lição mostra como criar rapidamente um documento HTML com texto e gráficos e usar WebView para imprimi-lo.

Carregar um documento HTML

Imprimir um documento HTML com WebView envolve carregar um recurso HTML ou criar um documento HTML como uma string. Esta seção descreve como criar uma string HTML e carregá-la em uma WebView para impressão.

Esse objeto de visualização normalmente é usado como parte de um layout de atividade. No entanto, se o aplicativo não estiver usando um WebView, você poderá criar uma instância da classe especificamente para impressão. As principais etapas para a criação dessa visualização de impressão personalizada são as seguintes:

  1. Crie uma WebViewClient que inicie um trabalho de impressão após o carregamento do recurso HTML.
  2. Carregue o recurso HTML no objeto WebView.

O exemplo de código a seguir demonstra como criar um WebViewClient simples e carregar um documento HTML criado em tempo real:

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;
}

Observação: a chamada para gerar um trabalho de impressão ocorre no método onPageFinished() do WebViewClient criado na seção anterior. Se você não esperar a conclusão do carregamento da página, a saída da impressão poderá estar incompleta ou em branco ou falhar completamente.

Observação:o código de exemplo acima contém uma instância do objeto WebView para que ele não seja coletado como lixo antes da criação do trabalho de impressão. Faça o mesmo na sua própria implementação. Caso contrário, o processo de impressão pode falhar.

Caso queira incluir gráficos na página, coloque os arquivos gráficos no diretório assets/ do seu projeto e especifique um URL base no primeiro parâmetro do método loadDataWithBaseURL(), conforme mostrado no exemplo de código a seguir:

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);

Também é possível carregar uma página da Web para impressão substituindo o método loadDataWithBaseURL() por loadUrl(), conforme mostrado abaixo.

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");

Ao usar WebView para criar documentos de impressão, esteja ciente das seguintes limitações:

  • Não é possível adicionar cabeçalhos ou rodapés, incluindo números de página, ao documento.
  • As opções de impressão do documento HTML não incluem a capacidade de imprimir intervalos de páginas. Por exemplo: não é possível imprimir as páginas 2 a 4 de um documento HTML de 10 páginas.
  • Uma instância do WebView só pode processar um trabalho de impressão por vez.
  • Documentos HTML com atributos de impressão CSS, como propriedades de paisagem, não são compatíveis.
  • Não é possível usar JavaScript em um documento HTML para acionar a impressão.

Observação:o conteúdo de um objeto WebView incluído em um layout também pode ser impresso após carregar um documento.

Se você quiser criar uma saída de impressão mais personalizada e ter controle total do desenho do conteúdo na página impressa, vá para a próxima lição: Como imprimir documentos personalizados.

Depois de criar um WebView e carregar o conteúdo HTML, o aplicativo estará perto de concluir o processo de impressão. As próximas etapas são acessar o PrintManager, criar um adaptador de impressão e, finalmente, criar um trabalho de impressão. O exemplo a seguir ilustra como realizar essas etapas:

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);
}

Este exemplo salva uma instância do objeto PrintJob para uso do aplicativo, o que não é necessário. Seu aplicativo pode usar esse objeto para acompanhar o progresso do trabalho de impressão enquanto ele é processado. Essa abordagem é útil quando você quer monitorar o status do trabalho de impressão no seu aplicativo para verificar se houve conclusão, falha ou cancelamento do usuário. Não é necessário criar uma notificação no app, porque o framework de impressão cria automaticamente uma notificação do sistema para o trabalho de impressão.