【Android】实现打印照片、HTML 文档、PDF 文档和自定义文档功能

Android打印功能全解析

在 Android 4.4(API 级别 19)及更高版本中,框架提供直接从 Android 应用打印图片和文档的服务。本文章介绍如何在应用中启用打印功能,包括打印图片、HTML 页面以及创建要打印的自定义文档。

一、打印照片

Android 支持库 PrintHelper 类提供 一种简单的图片打印方法,用于简化图片打印操作。

1、缩放模式

  • 通过 setScaleMode() 方法,可设置打印时的图片缩放模式:
    • SCALE_MODE_FIT: 调整图片大小,以便在页面的可打印区域内完整显示图片。
    • SCALE_MODE_FILL:缩放图片,使其填充整个页面的可打印区域,但可能会裁剪图片的上下或左右边缘的某些部分。此模式为默认选项。
  • 两个缩放选项都能保持图片的现有宽高比不变

2、使用方法

  • 调用 printBitmap() 方法后,系统会显示打印界面,用户可以选择打印机和打印选项。
package com.android.androidfunctiondemo.printer

import android.content.Context
import android.graphics.BitmapFactory
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.print.PrintHelper
import com.android.androidfunctiondemo.R
import com.android.androidfunctiondemo.databinding.ActivityPrinterBinding

class PrintPhotoActivity: AppCompatActivity() {
   
   

    private lateinit var viewBinding: ActivityPrinterBinding

    override fun onCreate(savedInstanceState: Bundle?) {
   
   
        super.onCreate(savedInstanceState)
        viewBinding = ActivityPrinterBinding.inflate(layoutInflater)
        setContentView(viewBinding.root)

        viewBinding.print.setOnClickListener {
   
   
            doPhotoPrint(this)
        }
    }

    /**
     * 打印图片
     */
    private fun doPhotoPrint(context: Context) {
   
   
        try {
   
   
            val printHelper = PrintHelper(context)
            printHelper.scaleMode = PrintHelper.SCALE_MODE_FIT
            val bitmap = BitmapFactory.decodeResource(resources, R.mipmap.weather_sun)
            bitmap?.let {
   
   
                printHelper.printBitmap("photo-print", bitmap)
            }
        } catch (e: Exception) {
   
   
            e.printStackTrace()
        }
    }
}
  • 实现效果
    在这里插入图片描述

二、打印 HTML 文档

使用 WebView 类可打印 HTML 文档,支持直接加载 HTML 页面, 或者以字符串形式构建自定义 HTML 文档。

1、注意事项

  • 使用 WebView 创建打印文档时, 存在以下限制:
    • 不能向文档中添加页眉或页脚,包括页码。
    • HTML 文档的打印选项不支持打印页码选择,只能全部打印。
    • WebView 的实例一次只能处理一个打印作业。
    • 不能在 HTML 文档中使用 JavaScript 触发打印作业。

2、实现步骤

  • 创建 WebViewClient 类,用于监听 HTML 资源加载完成情况,若 HTML 资源已加载完成,则创建打印作业。
  • 将 HTML 资源加载到 WebView 对象中。

3、使用方法

  • 确保在 onPageFinished() 方法中调用打印任务。若没有等待页面显示 加载完成,则打印输出可能不完整或空白,或者可能完全失败。
  • 存储 WebView 对象,使其不会在打印作业之前进行垃圾回收,否则打印流程 可能会失败。
package com.android.androidfunctiondemo.printer

import android.content.Context
import android.os.Bundle
import android.print.PrintAttributes
import android.print.PrintManager
import android.util.Log
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
import com.android.androidfunctiondemo.databinding.ActivityPrinterBinding

class PrintHtmlActivity: AppCompatActivity() {
   
   

    private val tag = "PrintHtmlActivity"
    private lateinit var viewBinding: ActivityPrinterBinding

    private var globalWebView: WebView? = null

    override fun onCreate(savedInstanceState: Bundle?) {
   
   
        super.onCreate(savedInstanceState)
        viewBinding = ActivityPrinterBinding.inflate(layoutInflater)
        setContentView(viewBinding.root)

        viewBinding.print.setOnClickListener {
   
   
            doWebViewPrint(this)
        }
    }

    /**
     * 打印 HTML 文档
     */
    private fun doWebViewPrint(context: Context) {
   
   
        val webView = WebView(context)
        webView.webViewClient = object : WebViewClient() {
   
   
            override fun shouldOverrideUrlLoading(
                view: WebView?,
                request: WebResourceRequest?
            ): Boolean {
   
   
                return false
            }

            override fun onPageFinished(view: WebView?, url: String?) {
   
   
                Log.d(tag, "[onPageFinished] url: $url")
                view?.let {
   
   
                    createWebPrintJob(it)
                }
                globalWebView = null
            }
        }

        try {
   
   
            // 方法1:生成自定义 html 文档
            val htmlDocument = "<html><body><h1>Test Content</h1><p>Testing, testing, testing...</p></body></html>"
            webView.loadDataWithBaseURL(null, htmlDocument, "text/HTML", "UTF-8", null)

            // 方法2: 直接加载网页内容
//            webView.loadUrl("https://developer.android.google.cn/training/printing/html-docs?hl=zh-cn")

            globalWebView = webView
        } catch (e: Exception) {
   
   
            e.printStackTrace()
            globalWebView = null
        }
    }

    /**
     * 创建打印任务
     */
    private fun createWebPrintJob(webView: WebView) {
   
   
        try {
   
   
            val printManager = getSystemService(Context.PRINT_SERVICE) as PrintManager
            val jobName = "WebView Document"
            val printAdapter = webView.createPrintDocumentAdapter(jobName)
            printManager.print(jobName, printAdapter, PrintAttributes.Builder().build())
        } catch (e: Exception) {
   
   
            e.printStackTrace()
        }
    }
}
  • 实现效果
    在这里插入图片描述

三、打印 PDF 文档

1、实现步骤

  • 创建打印适配器。
  • 连接打印管理器。
  • 创建打印任务。

2、创建打印适配器

  • 打印适配器与 Android 打印框架交互,并处理打印过程的各个步骤。
  • 这个过程要求用户在创建打印文档之前选择打印机和打印选项。这些选择会影响最终输出,因为用户可以选择具有不同输出能力、不同页面大小或不同页面方向的打印机。在用户做出这些选择时,打印框架会要求适配器布局并生成打印文档,为最终输出做准备。
  • 一旦用户点击打印按钮,框架就会将最终的打印文档传递给打印服务提供商以进行输出。
  • 在打印过程中,用户可以选择取消打印操作,因此打印适配器还必须监听并响应取消请求。

(1)PrintDocumentAdapter 类

  • PrintDocumentAdapter 抽象类旨在处理打印生命周期,它有四个主要的回调方法。您必须在您的打印适配器中实现这些方法,以便与打印框架正确交互。
    • onStart(): 在打印过程开始时调用一次。如果应用程序有任何一次性准备任务需要执行,例如获取要打印数据的快照,可以在这里完成。在适配器中实现此方法并非强制要求
    • onLayout(): 每当用户更改影响输出的打印设置时(例如不同的页面大小或页面方向),此方法都会被调用,为应用程序提供了计算要打印页面布局的机会。此方法必须返回打印文档中预期的页数
    • onWrite(): 被调用来将打印页面渲染到一个将要打印的文件中。此方法可能在每次调用 onLayout() 之后被调用一次或多次。
    • onFinish(): 在打印过程结束时调用一次。如果应用程序有任何一次性清理任务需要执行,可以在这里完成。在适配器中实现此方法并非强制要求
  • 这些适配器方法会在您应用程序的主线程中被调用。如果您预计在实现中这些方法的执行会比较耗时,那么应该将它们的执行封装到一个单独的线程中。例如,您可以将布局计算或打印文档的写入工作封装到单独的 AsyncTask 对象中。

(2)计算打印文档信息

  • onLayout() 方法指定正在创建的文档类型,并根据打印页面大小的信息计算打印作业的总页数。可通过 PrintDocumentInfo 类提供有关打印作业预期输出的信息,包括页数和内容类型。
  • onLayout() 方法的执行有三种结果:完成、取消,或者在无法完成布局计算时出现失败。通过调用 PrintDocumentAdapter.LayoutResu
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值