1# FormExtensionAbility(服务卡片) 2 3 4## 卡片概述 5 6FormExtensionAbility就是服务卡片扩展组件(以下简称“卡片”),是一种界面展示形式,可以将应用的重要信息或操作前置到卡片,以达到服务直达,减少体验层级的目的。 7 8卡片常用于嵌入到其他应用(当前只支持系统应用)中作为其界面的一部分显示,并支持拉起页面、发送消息等基础的交互功能。 9 10卡片的基本概念: 11 12- 卡片使用方:显示卡片内容的宿主应用,控制卡片在宿主中展示的位置。 13 14- 卡片管理服务:用于管理系统中所添加卡片的常驻代理服务,包括卡片对象的管理与使用,以及卡片周期性刷新等。 15 16- 卡片提供方:提供卡片显示内容原子化服务,控制卡片的显示内容、控件布局以及控件点击事件。 17 18 19## 运作机制 20 21卡片框架的运作机制如图1所示。 22 23 **图1** 卡片框架运作机制(Stage模型) 24 25 26卡片使用方包含以下模块: 27 28- 卡片使用:包含卡片的创建、删除、请求更新等操作。 29 30- 通信适配层:由OpenHarmony SDK提供,负责与卡片管理服务通信,用于将卡片的相关操作到卡片管理服务。 31 32卡片管理服务包含以下模块: 33 34- 周期性刷新:在卡片添加后,根据卡片的刷新策略启动定时任务周期性触发卡片的刷新。 35 36- 卡片缓存管理:在卡片添加到卡片管理服务后,对卡片的视图信息进行缓存,以便下次获取卡片时可以直接返回缓存数据,降低时延。 37 38- 卡片生命周期管理:对于卡片切换到后台或者被遮挡时,暂停卡片的刷新;以及卡片的升级/卸载场景下对卡片数据的更新和清理。 39 40- 卡片使用方对象管理:对卡片使用方的RPC对象进行管理,用于使用方请求进行校验以及对卡片更新后的回调处理。 41 42- 通信适配层:负责与卡片使用方和提供方进行RPC通信。 43 44卡片提供方包含以下模块: 45 46- 卡片服务:由卡片提供方开发者实现,开发者实现生命周期处理创建卡片、更新卡片以及删除卡片等请求,提供相应的卡片服务。 47 48- 卡片提供方实例管理模块:由卡片提供方开发者实现,负责对卡片管理服务分配的卡片实例进行持久化管理。 49 50- 通信适配层:由OpenHarmony SDK提供,负责与卡片管理服务通信,用于将卡片的更新数据主动推送到卡片管理服务。 51 52>  **说明:** 53> 实际开发时只需要作为卡片提供方进行卡片内容的开发,卡片使用方和卡片管理服务由系统自动处理。 54 55 56## 接口说明 57 58FormExtensionAbility类拥有如下API接口,具体的API介绍详见[接口文档](../reference/apis/js-apis-app-form-formExtensionAbility.md)。 59 60| 接口名 | 描述 | 61| -------- | -------- | 62| onAddForm(want: Want): formBindingData.FormBindingData | 卡片提供方接收创建卡片的通知接口。 | 63| onCastToNormalForm(formId: string): void | 卡片提供方接收临时卡片转常态卡片的通知接口。 | 64| onUpdateForm(formId: string): void | 卡片提供方接收更新卡片的通知接口。 | 65| onChangeFormVisibility(newStatus: { [key: string]: number }): void | 卡片提供方接收修改可见性的通知接口。 | 66| onFormEvent(formId: string, message: string): void | 卡片提供方接收处理卡片事件的通知接口。 | 67| onRemoveForm(formId: string): void | 卡片提供方接收销毁卡片的通知接口。 | 68| onConfigurationUpdate(config: Configuration): void | 当系统配置更新时调用。 | 69| onShareForm?(formId: string): { [key: string]: any } | 卡片提供方接收卡片分享的通知接口。 | 70 71FormExtensionAbility类还拥有成员context,为FormExtensionContext类,具体的API介绍详见[接口文档](../reference/apis/js-apis-inner-application-formExtensionContext.md)。 72 73| 接口名 | 描述 | 74| -------- | -------- | 75| startAbility(want: Want, callback: AsyncCallback<void>): void | 回调形式拉起一个卡片所属应用的UIAbility(系统接口,三方应用不支持调用,需申请后台拉起权限)。 | 76| startAbility(want: Want): Promise<void> | Promise形式拉起一个卡片所属应用的UIAbility(系统接口,三方应用不支持调用,需申请后台拉起权限)。 | 77 78formProvider类有如下API接口,具体的API介绍详见[接口文档](../reference/apis/js-apis-app-form-formProvider.md)。 79 80| 接口名 | 描述 | 81| -------- | -------- | 82| setFormNextRefreshTime(formId: string, minute: number, callback: AsyncCallback<void>): void; | 设置指定卡片的下一次更新时间。 | 83| setFormNextRefreshTime(formId: string, minute: number): Promise<void>; | 设置指定卡片的下一次更新时间,以promise方式返回。 | 84| updateForm(formId: string, formBindingData: FormBindingData, callback: AsyncCallback<void>): void; | 更新指定的卡片。 | 85| updateForm(formId: string, formBindingData: FormBindingData): Promise<void>; | 更新指定的卡片,以promise方式返回。 | 86 87formBindingData类有如下API接口,具体的API介绍详见[接口文档](../reference/apis/js-apis-app-form-formBindingData.md)。 88 89| 接口名 | 描述 | 90| -------- | -------- | 91| createFormBindingData(obj?: Object \| string): FormBindingData | 创建一个FormBindingData对象。 | 92 93 94## 开发步骤 95 96Stage卡片开发,即基于[Stage模型](stage-model-development-overview.md)的卡片提供方开发,主要涉及如下关键步骤: 97 98- [创建卡片FormExtensionAbility](#创建卡片formextensionability):卡片生命周期回调函数FormExtensionAbility开发。 99 100- [配置卡片配置文件](#配置卡片配置文件):配置应用配置文件module.json5和profile配置文件。 101 102- [卡片数据交互](#卡片数据交互):对卡片信息进行持久化管理。 103 104- [卡片数据交互](#卡片数据交互):通过updateForm更新卡片显示的信息。 105 106- [开发卡片页面](#开发卡片页面):使用HML+CSS+JSON开发JS卡片页面。 107 108- [开发卡片事件](#开发卡片事件):为卡片添加router事件和message事件。 109 110 111### 创建卡片FormExtensionAbility 112 113创建Stage模型的卡片,需实现FormExtensionAbility生命周期接口。先参考[DevEco Studio服务卡片开发指南](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-development-service-widget-0000001263280425)生成服务卡片模板。 114 1151. 在EntryFormAbility.ts中,导入相关模块。 116 117 ```ts 118 import FormExtension from '@ohos.app.form.FormExtensionAbility'; 119 import formBindingData from '@ohos.app.form.formBindingData'; 120 import formInfo from '@ohos.app.form.formInfo'; 121 import formProvider from '@ohos.app.form.formProvider'; 122 import dataStorage from '@ohos.data.storage'; 123 ``` 124 1252. 在EntryFormAbility.ts中,实现FormExtension生命周期接口。 126 127 ```ts 128 export default class EntryFormAbility extends FormExtension { 129 onAddForm(want) { 130 console.info('[EntryFormAbility] onAddForm'); 131 // 使用方创建卡片时触发,提供方需要返回卡片数据绑定类 132 let obj = { 133 "title": "titleOnCreate", 134 "detail": "detailOnCreate" 135 }; 136 let formData = formBindingData.createFormBindingData(obj); 137 return formData; 138 } 139 onCastToNormalForm(formId) { 140 // 使用方将临时卡片转换为常态卡片触发,提供方需要做相应的处理 141 console.info('[EntryFormAbility] onCastToNormalForm'); 142 } 143 onUpdateForm(formId) { 144 // 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要重写该方法以支持数据更新 145 console.info('[EntryFormAbility] onUpdateForm'); 146 let obj = { 147 "title": "titleOnUpdate", 148 "detail": "detailOnUpdate" 149 }; 150 let formData = formBindingData.createFormBindingData(obj); 151 formProvider.updateForm(formId, formData).catch((error) => { 152 console.info('[EntryFormAbility] updateForm, error:' + JSON.stringify(error)); 153 }); 154 } 155 onChangeFormVisibility(newStatus) { 156 // 使用方发起可见或者不可见通知触发,提供方需要做相应的处理,仅系统应用生效 157 console.info('[EntryFormAbility] onChangeFormVisibility'); 158 } 159 onFormEvent(formId, message) { 160 // 若卡片支持触发事件,则需要重写该方法并实现对事件的触发 161 console.info('[EntryFormAbility] onFormEvent'); 162 } 163 onRemoveForm(formId) { 164 // 删除卡片实例数据 165 console.info('[EntryFormAbility] onRemoveForm'); 166 } 167 onConfigurationUpdate(config) { 168 console.info('[EntryFormAbility] nConfigurationUpdate, config:' + JSON.stringify(config)); 169 } 170 onAcquireFormState(want) { 171 return formInfo.FormState.READY; 172 } 173 } 174 ``` 175 176>  **说明:** 177> FormExtensionAbility不能常驻后台,即在卡片生命周期回调函数中无法处理长时间的任务。 178 179### 配置卡片配置文件 180 1811. 卡片需要在[module.json5配置文件](../quick-start/module-configuration-file.md)中的extensionAbilities标签下,配置ExtensionAbility相关信息。FormExtensionAbility需要填写metadata元信息标签,其中键名称为固定字符串"ohos.extension.form",资源为卡片的具体配置信息的索引。 182 配置示例如下: 183 184 185 ```json 186 { 187 "module": { 188 // ... 189 "extensionAbilities": [ 190 { 191 "name": "EntryFormAbility", 192 "srcEntrance": "./ets/entryformability/EntryFormAbility.ts", 193 "label": "$string:EntryFormAbility_label", 194 "description": "$string:EntryFormAbility_desc", 195 "type": "form", 196 "metadata": [ 197 { 198 "name": "ohos.extension.form", 199 "resource": "$profile:form_config" 200 } 201 ] 202 } 203 ] 204 } 205 } 206 ``` 207 2082. 卡片的具体配置信息。在上述FormExtensionAbility的元信息("metadata"配置项)中,可以指定卡片具体配置信息的资源索引。例如当resource指定为$profile:form_config时,会使用开发视图的resources/base/profile/目录下的form_config.json作为卡片profile配置文件。内部字段结构说明如下表所示。 209 **表1** 卡片profile配置文件 210 211 | 属性名称 | 含义 | 数据类型 | 是否可缺省 | 212 | -------- | -------- | -------- | -------- | 213 | name | 表示卡片的类名,字符串最大长度为127字节。 | 字符串 | 否 | 214 | description | 表示卡片的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。字符串最大长度为255字节。 | 字符串 | 可缺省,缺省为空。 | 215 | src | 表示卡片对应的UI代码的完整路径。 | 字符串 | 否 | 216 | window | 用于定义与显示窗口相关的配置。 | 对象 | 可缺省 | 217 | isDefault | 表示该卡片是否为默认卡片,每个Ability有且只有一个默认卡片。<br/>true:默认卡片。<br/>false:非默认卡片。 | 布尔值 | 否 | 218 | colorMode | 表示卡片的主题样式,取值范围如下:<br/>auto:自适应。<br/>dark:深色主题。<br/>light:浅色主题。 | 字符串 | 可缺省,缺省值为“auto”。 | 219 | supportDimensions | 表示卡片支持的外观规格,取值范围:<br/>1 \* 2:表示1行2列的二宫格。<br/>2 \* 2:表示2行2列的四宫格。<br/>2 \* 4:表示2行4列的八宫格。<br/>4 \* 4:表示4行4列的十六宫格。 | 字符串数组 | 否 | 220 | defaultDimension | 表示卡片的默认外观规格,取值必须在该卡片supportDimensions配置的列表中。 | 字符串 | 否 | 221 | updateEnabled | 表示卡片是否支持周期性刷新,取值范围:<br/>true:表示支持周期性刷新,可以在定时刷新(updateDuration)和定点刷新(scheduledUpdateTime)两种方式任选其一,优先选择定时刷新。<br/>false:表示不支持周期性刷新。 | 布尔类型 | 否 | 222 | scheduledUpdateTime | 表示卡片的定点刷新的时刻,采用24小时制,精确到分钟。<br/>updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。 | 字符串 | 可缺省,缺省值为“0:0”。 | 223 | updateDuration | 表示卡片定时刷新的更新周期,单位为30分钟,取值为自然数。<br/>当取值为0时,表示该参数不生效。<br/>当取值为正整数N时,表示刷新周期为30\*N分钟。<br/>updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。 | 数值 | 可缺省,缺省值为“0”。 | 224 | formConfigAbility | 表示卡片的配置跳转链接,采用URI格式。 | 字符串 | 可缺省,缺省值为空。 | 225 | formVisibleNotify | 标识是否允许卡片使用卡片可见性通知。 | 字符串 | 可缺省,缺省值为空。 | 226 | metaData | 表示卡片的自定义信息,包含customizeData数组标签。 | 对象 | 可缺省,缺省值为空。 | 227 228 配置示例如下: 229 230 ```json 231 { 232 "forms": [ 233 { 234 "name": "widget", 235 "description": "This is a service widget.", 236 "src": "./js/widget/pages/index/index", 237 "window": { 238 "designWidth": 720, 239 "autoDesignWidth": true 240 }, 241 "colorMode": "auto", 242 "isDefault": true, 243 "updateEnabled": true, 244 "scheduledUpdateTime": "10:30", 245 "updateDuration": 1, 246 "defaultDimension": "2*2", 247 "supportDimensions": [ 248 "2*2" 249 ] 250 } 251 ] 252 } 253 ``` 254 255 256### 卡片信息的持久化 257 258因大部分卡片提供方都不是常驻服务,只有在需要使用时才会被拉起获取卡片信息,且卡片管理服务支持对卡片进行多实例管理,卡片ID对应实例ID,因此若卡片提供方支持对卡片数据进行配置,则需要对卡片的业务数据按照卡片ID进行持久化管理,以便在后续获取、更新以及拉起时能获取到正确的卡片业务数据。 259 260 261```ts 262const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store"; 263async function storeFormInfo(formId: string, formName: string, tempFlag: boolean) { 264 // 此处仅对卡片ID:formId,卡片名:formName和是否为临时卡片:tempFlag进行了持久化 265 let formInfo = { 266 "formName": formName, 267 "tempFlag": tempFlag, 268 "updateCount": 0 269 }; 270 try { 271 const storage = await dataStorage.getStorage(DATA_STORAGE_PATH); 272 // put form info 273 await storage.put(formId, JSON.stringify(formInfo)); 274 console.info(`[EntryFormAbility] storeFormInfo, put form info successfully, formId: ${formId}`); 275 await storage.flush(); 276 } catch (err) { 277 console.error(`[EntryFormAbility] failed to storeFormInfo, err: ${JSON.stringify(err)}`); 278 } 279} 280 281export default class EntryFormAbility extends FormExtension { 282 // ... 283 onAddForm(want) { 284 console.info('[EntryFormAbility] onAddForm'); 285 286 let formId = want.parameters["ohos.extra.param.key.form_identity"]; 287 let formName = want.parameters["ohos.extra.param.key.form_name"]; 288 let tempFlag = want.parameters["ohos.extra.param.key.form_temporary"]; 289 // 将创建的卡片信息持久化,以便在下次获取/更新该卡片实例时进行使用 290 // 此接口请根据实际情况实现,具体请参考:FormExtAbility Stage模型卡片实例 291 storeFormInfo(formId, formName, tempFlag); 292 293 let obj = { 294 "title": "titleOnCreate", 295 "detail": "detailOnCreate" 296 }; 297 let formData = formBindingData.createFormBindingData(obj); 298 return formData; 299 } 300} 301``` 302 303且需要适配onRemoveForm卡片删除通知接口,在其中实现卡片实例数据的删除。 304 305 306```ts 307const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store"; 308async function deleteFormInfo(formId: string) { 309 try { 310 const storage = await dataStorage.getStorage(DATA_STORAGE_PATH); 311 // del form info 312 await storage.delete(formId); 313 console.info(`[EntryFormAbility] deleteFormInfo, del form info successfully, formId: ${formId}`); 314 await storage.flush(); 315 } catch (err) { 316 console.error(`[EntryFormAbility] failed to deleteFormInfo, err: ${JSON.stringify(err)}`); 317 } 318} 319 320// ... 321 322export default class EntryFormAbility extends FormExtension { 323 // ... 324 onRemoveForm(formId) { 325 console.info('[EntryFormAbility] onRemoveForm'); 326 // 删除之前持久化的卡片实例数据 327 // 此接口请根据实际情况实现,具体请参考:FormExtAbility Stage模型卡片实例 328 deleteFormInfo(formId); 329 } 330} 331``` 332 333具体的持久化方法可以参考[轻量级数据存储开发指导](../database/database-preference-guidelines.md)。 334 335需要注意的是,卡片使用方在请求卡片时传递给提供方应用的Want数据中存在临时标记字段,表示此次请求的卡片是否为临时卡片: 336 337- 常态卡片:卡片使用方会持久化的卡片; 338 339- 临时卡片:卡片使用方不会持久化的卡片; 340 341由于临时卡片的数据具有非持久化的特殊性,某些场景例如卡片服务框架死亡重启,此时临时卡片数据在卡片管理服务中已经删除,且对应的卡片ID不会通知到提供方,所以卡片提供方需要自己负责清理长时间未删除的临时卡片数据。同时对应的卡片使用方可能会将之前请求的临时卡片转换为常态卡片。如果转换成功,卡片提供方也需要对对应的临时卡片ID进行处理,把卡片提供方记录的临时卡片数据转换为常态卡片数据,防止提供方在清理长时间未删除的临时卡片时,把已经转换为常态卡片的临时卡片信息删除,导致卡片信息丢失。 342 343 344### 卡片数据交互 345 346当卡片应用需要更新数据时(如触发了定时更新或定点更新),卡片应用获取最新数据,并调用updateForm()接口主动触发卡片的更新。 347 348 349```ts 350onUpdateForm(formId) { 351 // 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要重写该方法以支持数据更新 352 console.info('[EntryFormAbility] onUpdateForm'); 353 let obj = { 354 "title": "titleOnUpdate", 355 "detail": "detailOnUpdate" 356 }; 357 let formData = formBindingData.createFormBindingData(obj); 358 // 调用updateForm接口去更新对应的卡片,仅更新入参中携带的数据信息,其他信息保持不变 359 formProvider.updateForm(formId, formData).catch((error) => { 360 console.info('[EntryFormAbility] updateForm, error:' + JSON.stringify(error)); 361 }); 362} 363``` 364 365 366### 开发卡片页面 367 368开发者可以使用类Web范式(HML+CSS+JSON)开发JS卡片页面。生成如下卡片页面,可以这样配置卡片页面文件: 369 370 371 372>  **说明:** 373> 当前仅支持JS扩展的类Web开发范式来实现卡片的UI界面。 374 375- HML:使用类Web范式的组件描述卡片的页面信息。 376 377 ```html 378 <div class="container"> 379 <stack> 380 <div class="container-img"> 381 <image src="/common/widget.png" class="bg-img"></image> 382 </div> 383 <div class="container-inner"> 384 <text class="title">{{title}}</text> 385 <text class="detail_text" onclick="routerEvent">{{detail}}</text> 386 </div> 387 </stack> 388 </div> 389 ``` 390 391- CSS:HML中类Web范式组件的样式信息。 392 393 ```css 394 .container { 395 flex-direction: column; 396 justify-content: center; 397 align-items: center; 398 } 399 400 .bg-img { 401 flex-shrink: 0; 402 height: 100%; 403 } 404 405 .container-inner { 406 flex-direction: column; 407 justify-content: flex-end; 408 align-items: flex-start; 409 height: 100%; 410 width: 100%; 411 padding: 12px; 412 } 413 414 .title { 415 font-size: 19px; 416 font-weight: bold; 417 color: white; 418 text-overflow: ellipsis; 419 max-lines: 1; 420 } 421 422 .detail_text { 423 font-size: 16px; 424 color: white; 425 opacity: 0.66; 426 text-overflow: ellipsis; 427 max-lines: 1; 428 margin-top: 6px; 429 } 430 ``` 431 432- JSON:卡片页面中的数据和事件交互。 433 434 ```json 435 { 436 "data": { 437 "title": "TitleDefault", 438 "detail": "TextDefault" 439 }, 440 "actions": { 441 "routerEvent": { 442 "action": "router", 443 "abilityName": "EntryAbility", 444 "params": { 445 "message": "add detail" 446 } 447 } 448 } 449 } 450 ``` 451 452 453### 开发卡片事件 454 455卡片支持为组件设置交互事件(action),包括**router**事件和**message**事件,其中router事件用于Ability跳转,message事件用于卡片开发人员自定义点击事件。 456 457关键步骤说明如下: 458 4591. 在HML中为组件设置onclick属性,其值对应到JSON文件的actions字段中。 460 4612. 设置router事件: 462 - action属性值为"router"。 463 - abilityName为跳转目标的Ability名(支持跳转FA模型的PageAbility组件和Stage模型的UIAbility组件),如目前DevEco Studio创建的Stage模型的UIAbility默认名为EntryAbility。 464 - params为传递给跳转目标Ability的自定义参数,可以按需填写。其值可以在目标Ability启动时的want中的parameters里获取。如Stage模型MainAbility的onCreate生命周期里的入参want的parameters字段下获取到配置的参数。 465 4663. 设置message事件: 467 - action属性值为"message"。 468 - params为message事件的用户自定义参数,可以按需填写。其值可以在卡片生命周期函数onFormEvent()中的message里获取。 469 470示例如下。 471 472- HML文件 473 474 ```html 475 <div class="container"> 476 <stack> 477 <div class="container-img"> 478 <image src="/common/widget.png" class="bg-img"></image> 479 </div> 480 <div class="container-inner"> 481 <text class="title" onclick="routerEvent">{{title}}</text> 482 <text class="detail_text" onclick="messageEvent">{{detail}}</text> 483 </div> 484 </stack> 485 </div> 486 ``` 487 488- CSS文件 489 490 ```css 491 .container { 492 flex-direction: column; 493 justify-content: center; 494 align-items: center; 495 } 496 497 .bg-img { 498 flex-shrink: 0; 499 height: 100%; 500 } 501 502 .container-inner { 503 flex-direction: column; 504 justify-content: flex-end; 505 align-items: flex-start; 506 height: 100%; 507 width: 100%; 508 padding: 12px; 509 } 510 511 .title { 512 font-size: 19px; 513 font-weight: bold; 514 color: white; 515 text-overflow: ellipsis; 516 max-lines: 1; 517 } 518 519 .detail_text { 520 font-size: 16px; 521 color: white; 522 opacity: 0.66; 523 text-overflow: ellipsis; 524 max-lines: 1; 525 margin-top: 6px; 526 } 527 ``` 528 529- JSON文件 530 531 ```json 532 { 533 "data": { 534 "title": "TitleDefault", 535 "detail": "TextDefault" 536 }, 537 "actions": { 538 "routerEvent": { 539 "action": "router", 540 "abilityName": "EntryAbility", 541 "params": { 542 "info": "router info", 543 "message": "router message" 544 } 545 }, 546 "messageEvent": { 547 "action": "message", 548 "params": { 549 "detail": "message detail" 550 } 551 } 552 } 553 } 554 ``` 555 556- 在UIAbility中接收router事件并获取参数 557 558 ```ts 559 import UIAbility from '@ohos.app.ability.UIAbility' 560 561 export default class EntryAbility extends UIAbility { 562 onCreate(want, launchParam) { 563 // 获取router事件中传递的info参数 564 if (want.parameters.info === "router info") { 565 // do something 566 // console.log("router info:" + want.parameters.info) 567 } 568 // 获取router事件中传递的message参数 569 if (want.parameters.message === "router message") { 570 // do something 571 // console.log("router message:" + want.parameters.message) 572 } 573 } 574 // ... 575 }; 576 ``` 577 578- 在FormExtensionAbility中接收message事件并获取参数 579 580 ```ts 581 import FormExtension from '@ohos.app.form.FormExtensionAbility'; 582 583 export default class FormAbility extends FormExtension { 584 // ... 585 onFormEvent(formId, message) { 586 // 获取message事件中传递的detail参数 587 let msg = JSON.parse(message) 588 if (msg.params.detail === "message detail") { 589 // do something 590 // console.log("message info:" + msg.params.detail) 591 } 592 } 593 // ... 594 }; 595 ``` 596 597## 相关实例 598 599针对Stage模型卡片提供方的开发,有以下相关实例可供参考: 600 601- [FormExtAbility:Stage模型卡片(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-3.2-Release/ability/FormExtAbility) 602 603- [GalleryForm:图库卡片(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-3.2-Release/ability/GalleryForm) 604