1# 使用剪贴板进行延迟复制粘贴 2 3## 场景介绍 4 5[剪贴板服务](../../reference/apis-basic-services-kit/js-apis-pasteboard.md)主要提供管理系统剪贴板的能力,为系统复制、粘贴功能提供支持。 6 7反复执行复制操作时,剪贴板缓存中会存储多余数据从而导致内存增加,为了优化内存以及后续支持指定数据类型粘贴,剪贴板提供了延迟复制粘贴的功能。 8 9用户复制使用延迟粘贴技术的应用内的数据时,该条真实数据不会立即写入剪贴板服务的缓存中,而是等需要粘贴时,再从应用获取数据。 10 11## 约束限制 12 13- 剪贴板内容大小<128MB时支持使用。 14 15## 使用基于Record级别的延迟复制粘贴(推荐) 16 17本方案可以在粘贴前查询数据type信息,应用可以据此决定是否向剪贴板请求数据,因此建议使用本方案实现延迟复制功能。 18 19### 接口说明 20 21详细接口见[Pasteboard文档](../../reference/apis-basic-services-kit/_pasteboard.md)和[UDMF接口文档](../../reference/apis-arkdata/_u_d_m_f.md)。 22 23| 名称 | 说明 | 24| -------- |----------------------------------------------------------------------| 25| OH_UdmfRecordProvider* OH_UdmfRecordProvider_Create() | 创建一个指向统一数据提供者的指针。 | 26| int OH_UdmfRecordProvider_SetData(OH_UdmfRecordProvider* provider, void* context, const OH_UdmfRecordProvider_GetData callback, const UdmfData_Finalize finalize) | 设置统一数据提供者的回调函数。 | 27| int OH_UdmfRecord_SetProvider(OH_UdmfRecord* pThis, const char* const* types, unsigned int count, OH_UdmfRecordProvider* provider) | 将统一数据提供者配置到OH_UdmfRecord中。 | 28| int OH_Pasteboard_SetData(OH_Pasteboard* pasteboard, OH_UdmfData* data) | 向剪贴板中写入数据。 | 29| OH_UdmfData * OH_Pasteboard_GetData (OH_Pasteboard* pasteboard, int* status) | 获取剪贴板中的数据。 | 30| OH_UdmfRecord** OH_UdmfData_GetRecords(OH_UdmfData* pThis, unsigned int* count) | 获取OH_UdmfData中全部的数据记录。 | 31 32### 开发步骤 33 34 下面以超链接hyperlink类型数据场景为例,说明如何延迟发送数据。 35 36 为了代码可读性,代码中省略了各个步骤操作结果的校验,实际开发中需要确认每次调用的成功。 37 381. 引用头文件。 39 40 ```c 41 #include <database/pasteboard/oh_pasteboard.h> 42 #include <database/udmf/udmf.h> 43 #include <database/udmf/udmf_meta.h> 44 #include <database/udmf/uds.h> 45 ``` 46 472. 定义OH_UdmfRecordProvider的数据提供函数和实例注销回调函数。 48 49 ```c 50 // 1. 获取数据时触发的提供剪贴板数据的回调函数。 51 void* GetDataCallback(void* context, const char* type) { 52 if (strcmp(type, UDMF_META_HYPERLINK) == 0) { 53 // 2. 创建超链接hyperlink数据的UDS数据结构。 54 OH_UdsHyperlink* hyperlink = OH_UdsHyperlink_Create(); 55 // 3. 设置hyperlink中的URL和描述信息。 56 OH_UdsHyperlink_SetUrl(hyperlink, "www.demo.com"); 57 OH_UdsHyperlink_SetDescription(hyperlink, "This is www.demo.com description."); 58 return hyperlink; 59 } 60 return nullptr; 61 } 62 // 4. OH_UdmfRecordProvider销毁时触发的回调函数。 63 void ProviderFinalizeCallback(void* context) { printf("OH_UdmfRecordProvider finalize."); } 64 ``` 65 663. 在剪贴板中准备延迟复制数据。需要注意,此步骤完成后超链接类型数据并未真正写入数据库,只有当数据使用者从OH_UdmfRecord中获取OH_UdsHyperlink时,才会触发上文定义的`GetDataCallback`数据提供函数,从中得到数据。 67 68 ```c 69 // 5. 创建一个OH_UdmfRecord对象,并将OH_UdmfRecordProvider配置到其中。 70 OH_UdmfRecord* record = OH_UdmfRecord_Create(); 71 72 // 6. 创建一个统一数据提供者,并配置它提供数据、销毁时的两个回调函数。 73 OH_UdmfRecordProvider* provider = OH_UdmfRecordProvider_Create(); 74 OH_UdmfRecordProvider_SetData(provider, (void*)record, GetDataCallback, ProviderFinalizeCallback); 75 const char* types[1] = { UDMF_META_HYPERLINK }; 76 OH_UdmfRecord_SetProvider(record, types, 1, provider); 77 78 // 7. 创建OH_UdmfData对象,并向OH_UdmfData中添加OH_UdmfRecord。 79 OH_UdmfData* setData = OH_UdmfData_Create(); 80 OH_UdmfData_AddRecord(setData, record); 81 82 // 8. 创建OH_Pasteboard对象,将数据写入剪贴板中。 83 OH_Pasteboard* pasteboard = OH_Pasteboard_Create(); 84 OH_Pasteboard_SetData(pasteboard, setData); 85 ``` 86 874. 在剪贴板中获取延迟复制数据。 88 89 ```c 90 // 9. 剪贴板中获取延迟复制数据 91 int status = -1; 92 OH_UdmfData* getData = OH_Pasteboard_GetData(pasteboard, &status); 93 94 // 10. 获取数据中records 95 unsigned int count = 0; 96 OH_UdmfRecord** getRecords = OH_UdmfData_GetRecords(getData, &count); 97 98 // 11. 创建OH_UdsHyperlink对象,并从records中获取超链接类型数据 99 OH_UdsHyperlink* getHyperlink = OH_UdsHyperlink_Create(); 100 OH_UdmfRecord_GetHyperlink(getRecords[0], getHyperlink); 101 102 // 12. 获取超链接类型数据中的URL和描述信息。 103 const char* getUrl = OH_UdsHyperlink_GetUrl(getHyperlink); 104 const char* getDescription = OH_UdsHyperlink_GetDescription(getHyperlink); 105 ``` 106 1075. 使用完毕后删除相关对象。 108 109 ```c 110 OH_UdsHyperlink_Destroy(getHyperlink); 111 OH_UdmfRecordProvider_Destroy(provider); 112 OH_UdmfRecord_Destroy(record); 113 OH_UdmfData_Destroy(setData); 114 OH_UdmfData_Destroy(getData); 115 OH_Pasteboard_Destroy(pasteboard); 116 ``` 117 118 119## 使用基于PasteData级别的延迟复制粘贴 120 121本方案不支持粘贴前对数据type的查询。 122 123### 接口说明 124 125| 名称 | 说明 | 126| -------- |----------------------------------------------------------------------| 127| setUnifiedData(data: udc.UnifiedData): Promise\<void> | 将统一数据类型的数据写入系统剪贴板,在使用延迟复制粘贴功能时,不可与getUnifiedDataSync同线程调用。| 128| setUnifiedDataSync(data: udc.UnifiedData): void | 将统一数据类型的数据写入系统剪贴板,此接口为同步接口,在使用延迟复制粘贴功能时,不可与getUnifiedDataSync同线程调用。| 129| getUnifiedData(): Promise\<udc.UnifiedData> | 从系统剪贴板中读取统一数据类型的数据。| 130| getUnifiedDataSync(): udc.UnifiedData | 从系统剪贴板中读取统一数据类型的数据,此接口为同步接口,在使用延迟复制粘贴功能时,不可与setUnifiedData和setUnifiedDataSync同线程调用。| 131| setAppShareOptions(shareOptions: ShareOption): void | 应用设置本应用剪贴板数据的可粘贴范围。| 132| removeAppShareOptions(): void | 应用删除本应用设置的剪贴板数据可粘贴范围配置。| 133 134### 开发步骤 135 1361. 导入pasteboard,unifiedDataChannel和uniformTypeDescriptor模块。 137 138 ```ts\ 139 import {unifiedDataChannel, uniformTypeDescriptor} from '@kit.ArkData'; 140 import {BusinessError, pasteboard} from '@kit.BasicServicesKit' 141 ``` 142 1432. 构造一条PlainText数据,并书写获取延时数据的函数。 144 145 ```ts 146 let plainTextData = new unifiedDataChannel.UnifiedData(); 147 let GetDelayPlainText = ((dataType:string) => { 148 let plainText = new unifiedDataChannel.PlainText(); 149 plainText.details = { 150 Key: 'delayPlaintext', 151 Value: 'delayPlaintext', 152 }; 153 plainText.textContent = 'delayTextContent'; 154 plainText.abstract = 'delayTextContent'; 155 plainTextData.addRecord(plainText); 156 return plainTextData; 157 }); 158 ``` 159 1603. 向系统剪贴板中存入一条PlainText数据。 161 162 ```ts 163 let SetDelayPlainText = (() => { 164 plainTextData.properties.shareOptions = unifiedDataChannel.ShareOptions.CROSS_APP; 165 // 跨应用使用时设置为CROSS_APP,本应用内使用时设置为IN_APP 166 plainTextData.properties.getDelayData = GetDelayPlainText; 167 pasteboard.getSystemPasteboard().setUnifiedData(plainTextData).then(()=>{ 168 // 存入成功,处理正常场景 169 }).catch((error: BusinessError) => { 170 // 处理异常场景 171 }); 172 }) 173 ``` 174 1754. 从系统剪贴板中读取这条text数据 176 177 ```ts 178 let GetPlainTextUnifiedData = (() => { 179 pasteboard.getSystemPasteboard().getUnifiedData().then((data) => { 180 let outputData = data; 181 let records = outputData.getRecords(); 182 if (records[0].getType() == uniformTypeDescriptor.UniformDataType.PLAIN_TEXT) { 183 let record = records[0] as unifiedDataChannel.PlainText; 184 console.log('GetPlainText success, type:' + records[0].getType + ', details:' + 185 JSON.stringify(record.details) + ', textContent:' + record.textContent + ', abstract:' + record.abstract); 186 } else { 187 console.log('Get Plain Text Data No Success, Type is: ' + records[0].getType()); 188 } 189 }).catch((error: BusinessError) => { 190 //处理异常场景 191 }) 192 }) 193 ``` 194 1955. 应用设置本应用剪贴板数据的可粘贴范围。 196 197 ```ts 198 let systemPasteboard: pasteboard.SystemPasteboard = pasteboard.getSystemPasteboard(); 199 try { 200 systemPasteboard.setAppShareOptions(pasteboard.ShareOption.INAPP); 201 console.info('Set app share options success.'); 202 } catch (err) { 203 let error: BusinessError = err as BusinessError; 204 //处理异常场景 205 } 206 ``` 207 2086. 应用删除本应用设置的剪贴板数据可粘贴范围配置。 209 210 ```ts 211 let systemPasteboard: pasteboard.SystemPasteboard = pasteboard.getSystemPasteboard(); 212 try { 213 systemPasteboard.removeAppShareOptions(); 214 console.info('Remove app share options success.'); 215 } catch (err) { 216 let error: BusinessError = err as BusinessError; 217 //处理异常场景 218 } 219 ```