Печать HTML-документов

Для печати контента, помимо простой фотографии, на Android требуется составить текст и графику в печатном документе. Фреймворк Android позволяет использовать HTML для создания документа и его печати с минимальным количеством кода.

В Android 4.4 (уровень API 19) класс WebView был обновлен, чтобы обеспечить печать HTML-контента. Этот класс позволяет загрузить локальный ресурс HTML или скачать страницу из интернета, создать задание печати и передать его службам печати Android.

В этом уроке показано, как быстро создать HTML-документ, содержащий текст и графику, и использовать WebView для его печати.

Загрузка HTML-документа

Чтобы распечатать HTML-документ с помощью WebView, нужно загрузить HTML-ресурс или создать HTML-документ в виде строки. В этом разделе описывается, как создать строку HTML и загрузить ее в WebView для печати.

Этот объект представления обычно используется как часть макета действия. Однако если в вашем приложении не используется WebView, вы можете создать экземпляр класса специально для печати. Вот основные шаги для создания такого представления:

  1. Создайте WebViewClient, который запускает задание печати после загрузки ресурса HTML.
  2. Загрузите HTML-ресурс в объект WebView.

В приведенном ниже примере кода показано, как создать простой объект WebViewClient и загрузить HTML-документ, созданный на лету.

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

Примечание. Убедитесь, что вызов для создания задания печати происходит в методе onPageFinished() класса WebViewClient, который вы создали в предыдущем разделе. Если вы не дождетесь окончания загрузки страницы, распечатанный документ может быть неполным или пустым, или печать может не удаться.

Примечание. В приведенном выше примере кода содержится экземпляр объекта WebView, поэтому он не удаляется до создания задания печати. Убедитесь, что вы сделали то же самое в своей реализации, иначе процесс печати может завершиться ошибкой.

Если вы хотите включить в страницу графику, поместите графические файлы в каталог assets/ проекта и укажите базовый URL в первом параметре метода loadDataWithBaseURL(), как показано в следующем примере кода:

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

Вы также можете загрузить веб-страницу для печати, заменив метод loadDataWithBaseURL() на loadUrl(), как показано ниже.

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

При использовании WebView для создания печатных документов следует учитывать следующие ограничения:

  • В документ нельзя добавить верхние и нижние колонтитулы, в том числе номера страниц.
  • В настройках печати HTML-документа нет возможности указать диапазон страниц. Например, нельзя распечатать страницы со второй по четвертую из десяти.
  • Экземпляр WebView может обрабатывать только одно задание печати за раз.
  • HTML-документы, содержащие атрибуты печати CSS, например свойства альбомной ориентации, не поддерживаются.
  • Вы не можете использовать JavaScript в HTML-документе для запуска печати.

Примечание. Контент объекта WebView, включенного в макет, также можно распечатать после загрузки документа.

Если вы хотите настроить печать и полностью контролировать содержимое на печатной странице, перейдите к следующему уроку: Печать пользовательского документа.

После создания объекта WebView и загрузки HTML-контента приложение практически готово к печати. Далее необходимо получить доступ к PrintManager, создать адаптер печати и, наконец, создать задание печати. Ниже приведен пример того, как это сделать.

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

В этом примере экземпляр объекта PrintJob сохраняется для использования приложением, но это необязательно. Приложение может использовать этот объект для отслеживания хода выполнения задания печати. Этот подход полезен, если вы хотите отслеживать статус задания печати в приложении, чтобы узнать, было ли оно выполнено, отменено пользователем или произошел сбой. Создавать уведомление в приложении не требуется, поскольку фреймворк печати автоматически создает системное уведомление для задания печати.