onShareForm” />接口文档。接口名 描述 setFormNextRefreshTime(formId: string, minute: number, callback: AsyncCallback): void; 设置指定卡片的下一次更新时间。 setFormNextRefreshTime(formId: string, minute: number): Promise; 设置指定卡片的下一次更新时间,以promise方式返回。 updateForm(formId: string, formBindingData: FormBindingData, callback: AsyncCallback): void; 更新指定的卡片。 updateForm(formId: string, formBindingData: FormBindingData): Promise; 更新指定的卡片,以promise方式返回。
formBindingData类有如下API接口,具体的API介绍详见接口文档。
接口名 描述 createFormBindingData(obj?: Object | string): FormBindingData 创建一个FormBindingData对象。
开发步骤 Stage卡片开发,即基于Stage模型的卡片提供方开发,主要涉及如下关键步骤:
创建卡片FormExtensionAbility:卡片生命周期回调函数FormExtensionAbility开发。 配置卡片配置文件:配置应用配置文件module.json5和profile配置文件。 卡片信息的持久化:对卡片信息进行持久化管理。 卡片数据交互:通过updateForm更新卡片显示的信息。 开发卡片页面:使用HML+CSS+JSON开发JS卡片页面。 开发卡片事件:为卡片添加router事件和message事件。 创建卡片FormExtensionAbility 创建Stage模型的卡片,需实现FormExtensionAbility生命周期接口。先参考DevEco Studio服务卡片开发指南生成服务卡片模板。
在EntryFormAbility.ts中,导入相关模块。
import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility' ; import formBindingData from '@ohos.app.form.formBindingData' ; import formInfo from '@ohos.app.form.formInfo' ; import formProvider from '@ohos.app.form.formProvider' ; import dataStorage from '@ohos.data.storage' ;
在EntryFormAbility.ts中,实现FormExtension生命周期接口。
export default class EntryFormAbility extends FormExtensionAbility { onAddForm ( want ) { console. info ( '[EntryFormAbility] onAddForm' ) ; let obj = { "title" : "titleOnCreate" , "detail" : "detailOnCreate" } ; let formData = formBindingData. createFormBindingData ( obj) ; return formData; } onCastToNormalForm ( formId ) { console. info ( '[EntryFormAbility] onCastToNormalForm' ) ; } onUpdateForm ( formId ) { console. info ( '[EntryFormAbility] onUpdateForm' ) ; let obj = { "title" : "titleOnUpdate" , "detail" : "detailOnUpdate" } ; let formData = formBindingData. createFormBindingData ( obj) ; formProvider. updateForm ( formId, formData) . catch ( ( error ) => { console. info ( '[EntryFormAbility] updateForm, error:' + JSON . stringify ( error) ) ; } ) ; } onChangeFormVisibility ( newStatus ) { console. info ( '[EntryFormAbility] onChangeFormVisibility' ) ; } onFormEvent ( formId, message ) { console. info ( '[EntryFormAbility] onFormEvent' ) ; } onRemoveForm ( formId ) { console. info ( '[EntryFormAbility] onRemoveForm' ) ; } onConfigurationUpdate ( config ) { console. info ( '[EntryFormAbility] nConfigurationUpdate, config:' + JSON . stringify ( config) ) ; } onAcquireFormState ( want ) { return formInfo. FormState. READY ; } }
说明
FormExtensionAbility不能常驻后台,即在卡片生命周期回调函数中无法处理长时间的任务。
配置卡片配置文件 卡片需要在module.json5配置文件中的extensionAbilities标签下,配置ExtensionAbility相关信息。FormExtensionAbility需要填写metadata元信息标签,其中键名称为固定字符串”ohos.extension.form”,资源为卡片的具体配置信息的索引。
配置示例如下:
{ "module" : { ... "extensionAbilities" : [ { "name" : "EntryFormAbility" , "srcEntrance" : "./ets/entryformability/EntryFormAbility.ts" , "label" : "$string:EntryFormAbility_label" , "description" : "$string:EntryFormAbility_desc" , "type" : "form" , "metadata" : [ { "name" : "ohos.extension.form" , "resource" : "$profile:form_config" } ] } ] } }
卡片的具体配置信息。在上述FormExtensionAbility的元信息(”metadata”配置项)中,可以指定卡片具体配置信息的资源索引。例如当resource指定为$profile:form_config时,会使用开发视图的resources/base/profile/目录下的form_config.json作为卡片profile配置文件。内部字段结构说明如下表所示。
表1 卡片profile配置文件
属性名称 含义 数据类型 是否可缺省 name 表示卡片的类名,字符串最大长度为127字节。 字符串 否 description 表示卡片的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。字符串最大长度为255字节。 字符串 可缺省,缺省为空。 src 表示卡片对应的UI代码的完整路径。 字符串 否 window 用于定义与显示窗口相关的配置。 对象 可缺省 isDefault 表示该卡片是否为默认卡片,每个UIAbility有且只有一个默认卡片。- true:默认卡片。- false:非默认卡片。 布尔值 否 colorMode 表示卡片的主题样式,取值范围如下:- auto:自适应。- dark:深色主题。- light:浅色主题。 字符串 可缺省,缺省值为“auto”。 supportDimensions 表示卡片支持的外观规格,取值范围:- 1 * 2:表示1行2列的二宫格。- 2 * 2:表示2行2列的四宫格。- 2 * 4:表示2行4列的八宫格。- 4 * 4:表示4行4列的十六宫格。 字符串数组 否 defaultDimension 表示卡片的默认外观规格,取值必须在该卡片supportDimensions配置的列表中。 字符串 否 updateEnabled 表示卡片是否支持周期性刷新,取值范围:- true:表示支持周期性刷新,可以在定时刷新(updateDuration)和定点刷新(scheduledUpdateTime)两种方式任选其一,优先选择定时刷新。- false:表示不支持周期性刷新。 布尔类型 否 scheduledUpdateTime 表示卡片的定点刷新的时刻,采用24小时制,精确到分钟。updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。 字符串 可缺省,缺省值为“0:0”。 updateDuration 表示卡片定时刷新的更新周期,单位为30分钟,取值为自然数。当取值为0时,表示该参数不生效。当取值为正整数N时,表示刷新周期为30*N分钟。updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。 数值 可缺省,缺省值为“0”。 formConfigAbility 表示卡片的配置跳转链接,采用URI格式。 字符串 可缺省,缺省值为空。 formVisibleNotify 标识是否允许卡片使用卡片可见性通知。 字符串 可缺省,缺省值为空。 metaData 表示卡片的自定义信息,包含customizeData数组标签。 对象 可缺省,缺省值为空。
配置示例如下:
{ "forms" : [ { "name" : "widget" , "description" : "This is a service widget." , "src" : "./js/widget/pages/index/index" , "window" : { "designWidth" : 720 , "autoDesignWidth" : true } , "colorMode" : "auto" , "isDefault" : true , "updateEnabled" : true , "scheduledUpdateTime" : "10:30" , "updateDuration" : 1 , "defaultDimension" : "2*2" , "supportDimensions" : [ "2*2" ] } ] }
卡片信息的持久化 因大部分卡片提供方都不是常驻服务,只有在需要使用时才会被拉起获取卡片信息,且卡片管理服务支持对卡片进行多实例管理,卡片ID对应实例ID,因此若卡片提供方支持对卡片数据进行配置,则需要对卡片的业务数据按照卡片ID进行持久化管理,以便在后续获取、更新以及拉起时能获取到正确的卡片业务数据。
const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store" ; async function storeFormInfo ( formId : string, formName : string, tempFlag : boolean) { let formInfo = { "formName" : formName, "tempFlag" : tempFlag, "updateCount" : 0 } ; try { const storage = await dataStorage. getStorage ( DATA_STORAGE_PATH ) ; await storage. put ( formId, JSON . stringify ( formInfo) ) ; console. info ( ` [EntryFormAbility] storeFormInfo, put form info successfully, formId: ${ formId} ` ) ; await storage. flush ( ) ; } catch ( err) { console. error ( ` [EntryFormAbility] failed to storeFormInfo, err: ${ JSON . stringify ( err) } ` ) ; } } export default class EntryFormAbility extends FormExtension { ... onAddForm ( want ) { console. info ( '[EntryFormAbility] onAddForm' ) ; let formId = want. parameters[ "ohos.extra.param.key.form_identity" ] ; let formName = want. parameters[ "ohos.extra.param.key.form_name" ] ; let tempFlag = want. parameters[ "ohos.extra.param.key.form_temporary" ] ; storeFormInfo ( formId, formName, tempFlag) ; let obj = { "title" : "titleOnCreate" , "detail" : "detailOnCreate" } ; let formData = formBindingData. createFormBindingData ( obj) ; return formData; } }
且需要适配onRemoveForm卡片删除通知接口,在其中实现卡片实例数据的删除。
const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store" ; async function deleteFormInfo ( formId : string) { try { const storage = await dataStorage. getStorage ( DATA_STORAGE_PATH ) ; await storage. delete ( formId) ; console. info ( ` [EntryFormAbility] deleteFormInfo, del form info successfully, formId: ${ formId} ` ) ; await storage. flush ( ) ; } catch ( err) { console. error ( ` [EntryFormAbility] failed to deleteFormInfo, err: ${ JSON . stringify ( err) } ` ) ; } } ... export default class EntryFormAbility extends FormExtension { ... onRemoveForm ( formId ) { console. info ( '[EntryFormAbility] onRemoveForm' ) ; deleteFormInfo ( formId) ; } }
具体的持久化方法可以参考应用数据持久化概述。
需要注意的是,卡片使用方在请求卡片时传递给提供方应用的Want数据中存在临时标记字段,表示此次请求的卡片是否为临时卡片:
常态卡片:卡片使用方会持久化的卡片; 临时卡片:卡片使用方不会持久化的卡片; 由于临时卡片的数据具有非持久化的特殊性,某些场景例如卡片服务框架死亡重启,此时临时卡片数据在卡片管理服务中已经删除,且对应的卡片ID不会通知到提供方,所以卡片提供方需要自己负责清理长时间未删除的临时卡片数据。同时对应的卡片使用方可能会将之前请求的临时卡片转换为常态卡片。如果转换成功,卡片提供方也需要对对应的临时卡片ID进行处理,把卡片提供方记录的临时卡片数据转换为常态卡片数据,防止提供方在清理长时间未删除的临时卡片时,把已经转换为常态卡片的临时卡片信息删除,导致卡片信息丢失。
卡片数据交互 当卡片应用需要更新数据时(如触发了定时更新或定点更新),卡片应用获取最新数据,并调用updateForm()接口主动触发卡片的更新。
onUpdateForm ( formId ) { console. info ( '[EntryFormAbility] onUpdateForm' ) ; let obj = { "title" : "titleOnUpdate" , "detail" : "detailOnUpdate" } ; let formData = formBindingData. createFormBindingData ( obj) ; formProvider. updateForm ( formId, formData) . catch ( ( error ) => { console. info ( '[EntryFormAbility] updateForm, error:' + JSON . stringify ( error) ) ; } ) ; }
开发卡片页面 开发者可以使用类Web范式(HML+CSS+JSON)开发JS卡片页面。生成如下卡片页面,可以这样配置卡片页面文件:
说明
当前仅支持JS扩展的类Web开发范式来实现卡片的UI。
HML:使用类Web范式的组件描述卡片的页面信息。
< div class = "container" > < stack> < div class = "container-img" > < image src= "/common/widget.png" class = "bg-img" > < / image> < / div> < div class = "container-inner" > < text class = "title" > { { title} } < / text> < text class = "detail_text" onclick= "routerEvent" > { { detail} } < / text> < / div> < / stack> < / div>
CSS:HML中类Web范式组件的样式信息。
. container { flex- direction: column; justify- content: center; align- items: center; } . bg- img { flex- shrink: 0 ; height : 100 % ; } . container- inner { flex- direction: column; justify- content: flex- end; align- items: flex- start; height : 100 % ; width : 100 % ; padding : 12px; } . title { font- size: 19px; font- weight: bold; color : white; text- overflow: ellipsis; max- lines: 1 ; } . detail_text { font- size: 16px; color : white; opacity : 0.66 ; text- overflow: ellipsis; max- lines: 1 ; margin- top: 6px; }
JSON:卡片页面中的数据和事件交互。
{ "data" : { "title" : "TitleDefault" , "detail" : "TextDefault" } , "actions" : { "routerEvent" : { "action" : "router" , "abilityName" : "EntryAbility" , "params" : { "message" : "add detail" } } } }
开发卡片事件 卡片支持为组件设置交互事件(action),包括router 事件和message 事件,其中router事件用于UIAbility跳转,message事件用于卡片开发人员自定义点击事件。
关键步骤说明如下:
在HML中为组件设置onclick属性,其值对应到JSON文件的actions字段中。 设置router事件:action属性值为”router”。 abilityName为跳转目标的UIAbility名(支持跳转FA模型的PageAbility组件和Stage模型的UIAbility组件),如目前DevEco Studio创建的Stage模型的UIAbility默认名为EntryAbility。 params为传递给跳转目标UIAbility的自定义参数,可以按需填写。其值可以在目标UIAbility启动时的want中的parameters里获取。如Stage模型MainAbility的onCreate生命周期里的入参want的parameters字段下获取到配置的参数。 设置message事件:action属性值为”message”。 params为message事件的用户自定义参数,可以按需填写。其值可以在卡片生命周期函数onFormEvent()中的message里获取。 示例如下。
HML文件
< div class = "container" > < stack> < div class = "container-img" > < image src= "/common/widget.png" class = "bg-img" > < / image> < / div> < div class = "container-inner" > < text class = "title" onclick= "routerEvent" > { { title} } < / text> < text class = "detail_text" onclick= "messageEvent" > { { detail} } < / text> < / div> < / stack> < / div>
CSS文件
. container { flex- direction: column; justify- content: center; align- items: center; } . bg- img { flex- shrink: 0 ; height : 100 % ; } . container- inner { flex- direction: column; justify- content: flex- end; align- items: flex- start; height : 100 % ; width : 100 % ; padding : 12px; } . title { font- size: 19px; font- weight: bold; color : white; text- overflow: ellipsis; max- lines: 1 ; } . detail_text { font- size: 16px; color : white; opacity : 0.66 ; text- overflow: ellipsis; max- lines: 1 ; margin- top: 6px; }
JSON文件
{ "data" : { "title" : "TitleDefault" , "detail" : "TextDefault" } , "actions" : { "routerEvent" : { "action" : "router" , "abilityName" : "EntryAbility" , "params" : { "info" : "router info" , "message" : "router message" } } , "messageEvent" : { "action" : "message" , "params" : { "detail" : "message detail" } } } }
在UIAbility中接收router事件并获取参数
import UIAbility from '@ohos.app.ability.UIAbility' export default class EntryAbility extends UIAbility { onCreate ( want, launchParam ) { let params = JSON . parse ( want. parameters. params) ; if ( params. info === "router info" ) { } if ( params. message === "router message" ) { } } ... } ;
在FormExtensionAbility中接收message事件并获取参数
import FormExtension from '@ohos.app.form.FormExtensionAbility' ; export default class FormAbility extends FormExtension { ... onFormEvent ( formId, message ) { let msg = JSON . parse ( message) if ( msg. detail === "message detail" ) { } } ... } ;