• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 文件打印(C/C++)
2
3<!--Kit: Basic Services Kit-->
4<!--Subsystem: Print-->
5<!--Owner: @guoshengbang-->
6<!--Designer: @gcw_4D6e0BBd-->
7<!--Tester: @guoshengbang-->
8<!--Adviser: @RayShih-->
9
10OS提供了两种打印方式:
11
12[方式一](#3-方式一通过接口拉起系统打印预览界面下发任务):应用通过接口拉起系统打印预览界面,传输渲染好的PDF文件进行打印任务下发。该方式适合有打印需求的应用使用系统能力快捷进行文件打印。
13
14[方式二](#4-方式二通过打印接口自主进行打印设备的发现连接和打印任务的下发):应用通过打印接口自主发现、连接打印设备并下发任务。该方式适合具有自己的打印预览界面的应用,可以通过接口打开打印设备发现、获取打印设备能力,构建打印预览界面需要的信息。
15
16> **说明:**
17>
18> 使用打印服务,需[声明权限](../../security/AccessToken/declare-permissions.md):ohos.permission.PRINT19>
20> 当不再使用打印服务时,调用OH_Print_Release()释放打印客户端资源并取消事件订阅。
21
22
23
24## 开发步骤
25
26### 1. 引用头文件
27
28```c++
29#include <cstdint>
30#include <cstdio>
31#include <cwchar>
32#include <vector>
33#include <string>
34#include "hilog/log.h"
35#include "napi/native_api.h"
36#include "BasicServicesKit/ohprint.h"
37```
38
39### 2. 在CMake脚本中添加动态链接库
40
41```txt
42target_link_libraries(entry PUBLIC
43    libace_napi.z.so
44    libhilog_ndk.z.so
45    libohprint.so
46)
47```
48
49### 3. 方式一:通过接口拉起系统打印预览界面下发任务
50
51```ts
52import { Context } from '@kit.AbilityKit';
53
54@Entry
55@Component
56struct Index {
57    build() {
58        Button("call native")
59            .onClick(() => {
60                let ctx = this.getUIContext().getHostContext();; // 获取 Ability 的 Context
61                if (ctx === undefined) {
62                    console.error('get fileUri or context failed');
63                    return;
64                }
65                getContext(ctx);                                 // 传给 C++ 侧
66            });
67    }
68}
69```
70
71```c++
72// 使用系统打印下发打印任务
73static void* context;
74static char* currentJobId;
75
76// 初始化打印服务
77Print_ErrorCode ret = OH_Print_Init();
78
79static napi_value getContext(napi_env env, napi_callback_info info)
80{
81    size_t argc = 1;
82    napi_value argv[1] = {nullptr};
83    // 假设 napi_get_cb_info 正常返回
84    napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
85    // 保存 context 于后续使用
86    napi_status ret = napi_unwrap(env, argv[0], &context);
87    return nullptr;
88}
89
90// 系统打印预览界面回调,首次拉起或用户修改打印参数时回调
91static void StartLayoutWriteCb(const char *jobId,
92                                uint32_t fd,
93                                const Print_PrintAttributes *oldAttrs,
94                                const Print_PrintAttributes *newAttrs,
95                                Print_WriteResultCallback writeCallback)
96{
97    // 缓存任务Id,任务Id唯一
98    currentJobId = jobId;
99    // WriteFile 由开发者实现,获取当前用户修改前后的打印参数,渲染对应的打印文件写入fd。如黑白彩色,指定页码等。
100    uint32_t retCode = WriteFile(fd, oldAttrs, newAttrs);
101    // 通知打印系统文件写入完成
102    writeCallback(jobId, retCode);
103}
104
105// 打印文件写入完成后,系统打印预览界面会进行预览,此时用户可以点击“开始打印”下发任务。
106// 任务ID对应的打印状态变化的回调函数。
107static void JobStateChangedCb(const char *jobId, uint32_t state)
108{
109    // 开发者根据任务id管理任务状态的逻辑
110}
111
112// 调用打印接口以拉起系统打印预览界面。
113char printJobName[] = "fileName";
114Print_PrintDocCallback printDocCallback = { StartLayoutWriteCb, JobStateChangedCb };
115Print_ErrorCode ret = OH_Print_StartPrintByNative(printJobName, printDocCallback, context);
116
117// 不再使用打印服务时释放资源
118OH_Print_Release()
119```
120
121### 4. 方式二:通过打印接口自主进行打印设备的发现、连接和打印任务的下发
122
123```c++
124// 初始化打印服务
125Print_ErrorCode ret = OH_Print_Init();
126
127// 注册设备发现事件的回调,开始打印设备发现
128static void PrinterDiscoveryCallback(Print_DiscoveryEvent event, const Print_PrinterInfo *printerInfo)
129{
130    // 发现一台打印设备,以设备Id作为唯一标识符
131    if (printerInfo == nullptr) {
132        OH_LOG_Print(LOG_APP, LOG_INFO, 0, "print c/c++", "printerInfo is nullptr");
133        return;
134    }
135    // 开发者需根据具体业务场景实现以下回调逻辑
136    switch (event) {
137        // 发现打印设备事件
138        case PRINTER_DISCOVERED:
139            OnPrinterDiscovered(printerInfo);
140            break;
141        // 丢失打印设备事件
142        case PRINTER_LOST:
143            OnPrinterLost(printerInfo);
144            break;
145        // 打印机连接开始事件,由OH_Print_ConnectPrinter触发
146        case PRINTER_CONNECTING:
147            OnPrinterConnecting(printerInfo);
148            break;
149        // 打印机连接完成事件,由OH_Print_ConnectPrinter触发
150        case PRINTER_CONNECTED:
151            OnPrinterConnected(printerInfo);
152            break;
153        default:
154            break;
155    }
156}
157Print_PrinterDiscoveryCallback callback = PrinterDiscoveryCallback;
158Print_ErrorCode ret = OH_Print_StartPrinterDiscovery(callback);
159
160// 连接打印机,通过PrinterDiscoveryCallback获取到打印机属性,使用打印机ID进行连接
161// 连接成功后会收到PRINTER_CONNECTED事件。
162Print_ErrorCode ret = OH_Print_ConnectPrinter(printerInfo->printerId);
163
164// 当不需要使用发现功能时,停止设备发现
165Print_ErrorCode ret = OH_Print_StopPrinterDiscovery();
166
167// 获取已添加的打印设备名称列表
168Print_StringList addedPrinterList = {0};
169Print_ErrorCode ret = OH_Print_QueryPrinterList(&addedPrinterList);
170for (uint32_t index = 0; index < addedPrinterList.count; index++) {
171    Print_PrinterInfo *printerInfo = nullptr;
172    // 使用已添加的打印设备名称来获取打印设备属性。
173    ret = OH_Print_QueryPrinterInfo(addedPrinterList[index], &printerInfo);
174    // 业务代码
175    // 打印设备属性使用完成后需要释放资源
176    OH_Print_ReleasePrinterInfo(printerInfo);
177}
178// 在使用完打印设备名称列表后需要释放该列表资源。
179OH_Print_ReleasePrinterList(&addedPrinterList);
180
181// 下发打印任务
182// 本例子使用默认选项 printerInfo->defaultValue 作为打印任务参数来下发任务。
183std::vector<uint32_t> fdList = { 44, 45 };
184Print_PrintJob* printJob = new Print_PrintJob{ jobName,
185                                               fdList.data(),
186                                               static_cast<uint32_t>(fdList.size()),
187                                               printerInfo->printerId,
188                                               1, // 打印份数
189                                               printerInfo->defaultValue.defaultPaperSource,
190                                               printerInfo->defaultValue.defaultMediaType,
191                                               printerInfo->defaultValue.defaultPageSizeId,
192                                               printerInfo->defaultValue.defaultColorMode,
193                                               printerInfo->defaultValue.defaultDuplexMode,
194                                               printerInfo->defaultValue.defaultResolution,
195                                               printerInfo->defaultValue.defaultMargin,
196                                               true,
197                                               printerInfo->defaultValue.defaultOrientation,
198                                               printerInfo->defaultValue.defaultPrintQuality,
199                                               DOCUMENT_FORMAT_PDF,
200                                               printerInfo->defaultValue.otherDefaultValues, };
201Print_ErrorCode ret = OH_Print_StartPrintJob(printJob);
202delete printJob;
203
204// 不再使用打印服务时释放资源
205OH_Print_Release()
206```