鸿蒙-服务卡片开发文档
一、服务卡片架构
卡片的基本概念:
● 卡片使用方:如上图中的桌面,显示卡片内容的宿主应用,控制卡片在宿主中展示的位置。
○ 应用图标:应用入口图标,点击后可拉起应用进程,图标内容不支持交互。
○ 卡片:具备不同规格大小的界面展示,卡片的内容可以进行交互,如实现按钮进行界面刷新、页面跳转等。
● 卡片提供方:包含卡片的应用,提供卡片的显示内容、控件布局以及控件点击处理逻辑。
○ FormExtensionAbility:卡片业务逻辑模块,提供卡片创建、销毁、刷新等生命周期回调。
○ 卡片页面:卡片UI模块,包含页面控件、布局、事件等显示和交互信息。
二、 开发方式
在Stage模型下,服务卡片的UI页面支持通过ArkTs和JS两种语言进行开发:
● 基于声明式范式ArkTS UI开发的卡片,简称ArkTS卡片。
● 基于类Web范式JS UI开发的卡片,简称JS卡片。
二者有一定的差别。ArkTs支持更多样化更动态的卡片开发。如果只是静态的JS卡片,可以考虑使用JS开发。
| 类别 | JS卡片 | ArkTS卡片 |
|---|---|---|
| 开发范式 | 类Web范式 | 声明式范式 |
| 组件能力 | 支持 | 支持 |
| 布局能力 | 支持 | 支持 |
| 事件能力 | 支持 | 支持 |
| 自定义动效 | 不支持 | 支持 |
| 自定义绘制 | 不支持 | 支持 |
| 逻辑代码执行(不包含import能力) | 不支持 | 支持 |
三、 ArkTs卡片机制
● 卡片使用方:显示卡片内容的宿主应用,控制卡片在宿主中展示的位置,当前仅系统应用可以作为卡片使用方(如系统桌面)。
● 卡片提供方:提供卡片显示内容的应用,控制卡片的显示内容、控件布局以及控件点击事件。
● 卡片管理服务:用于管理系统中所添加卡片的常驻代理服务,提供formProvider接口能力,同时提供卡片对象的管理与使用以及卡片周期性刷新等能力。
● 卡片渲染服务:用于管理卡片渲染实例,渲染实例与卡片使用方上的卡片组件一一绑定。卡片渲染服务运行卡片页面代码widgets.abc进行渲染,并将渲染后的数据发送至卡片使用方对应的卡片组件。
与JS卡片相比,ArkTS卡片支持在卡片中运行逻辑代码,为确保ArkTS卡片发生问题后不影响卡片使用方应用的使用,ArkTS卡片新增了卡片渲染服务用于运行卡片页面代码widgets.abc,卡片渲染服务由卡片管理服务管理。卡片使用方的每个卡片组件都对应了卡片渲染服务里的一个渲染实例,同一应用提供方的渲染实例运行在同一个虚拟机运行环境中,不同应用提供方的渲染实例运行在不同的虚拟机运行环境中,通过虚拟机运行环境隔离不同应用提供方卡片之间的资源与状态。开发过程中需要注意的是globalThis对象的使用,相同应用提供方的卡片globalThis对象是同一个,不同应用提供方的卡片globalThis对象是不同的。
ArkTS卡片相较于JS卡片具备了更加丰富的能力,但也增加了使用卡片进行恶意行为的风险。由于ArkTS卡片显示在使用方应用中,使用方应用一般为桌面应用,为确保桌面的使用体验以及功耗相关考虑,对ArkTS卡片的能力做了以下约束:
● 不支持加载so。
● 不支持使用native语言开发。
● 仅支持声明式范式的文档中心组件、事件、动效、数据管理、状态管理和API能力。
● 卡片的事件处理和使用方的事件处理是独立的,建议在使用方支持左右滑动的场景下卡片内容不要使用左右滑动功能的组件,以防手势冲突影响交互体验。
除此之外,当前ArkTS卡片还存在如下约束:
● 暂不支持导入模块。
● 暂不支持极速预览。
● 暂不支持断点调试能力。
● 暂不支持Hot Reload热重载。
四、 ArkTs卡片开发
1. 开发模块
● FormExtensionAbility为卡片扩展模块,提供卡片创建、销毁、刷新等生命周期回调。
● FormExtensionContext:FormExtensionAbility的上下文环境,提供FormExtensionAbility具有的接口和能力。
● FormProvider:提供了卡片提供方相关接口的能力,开发者在开发卡片时,可通过该模块提供接口实现更新卡片,设置卡片更新时间,获取卡片信息,请求发布卡片等
● FormInfo:提供对卡片的相关卡片信息和状态进行设置和查询的能力。
● FormBindingData:提供卡片数据绑定的能力,包括FormBindingData对象的创建、相关信息的描述。
● 页面布局(Card.ets):提供声明式范式的UI接口能力。
● 卡片配置:包含FormExtensionAbility的配置和卡片的配置
■ module.json中的extensionAbilities标签下,配置FormExtensionAbility相关信息。
■ 在resources/base/profile/目录下的form_config.json中,配置卡片(WidgetCard.ets)相关信息。
2. 开发实战
2.1 创建卡片
有三个模板供选择
选择创建后,目录下多出entryformability,widget1的card.ets和相关的profile文件。
2.2 配置卡片信息
主要配置aibility的配置和卡片的配置。ability的配置在创建卡片时为我们自动生成了一部分。
● 需要注意的是,FormExtensionAbility需要填写metadata元信息标签,其中键名称为固定字符串“ohos.extension.form”,资源为卡片的具体配置信息的索引。
如上文所说,metadata元信息标签里是卡片配置信息。我们根据开发需求进行配置。
附配置信息表。
| 属性名称 | 含义 | 数据类型 | 是否可缺省 |
|---|---|---|---|
| name | 表示卡片的类名,字符串最大长度为127字节。 | 字符串 | 否 |
| description | 表示卡片的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。字符串最大长度为255字节。该属性将显示在卡片预览界面上,以便用户识别不同卡片。 | 字符串 | 可缺省,缺省为空。 |
| src | 表示卡片对应的UI代码的完整路径。当为ArkTS卡片时,完整路径需要包含卡片文件的后缀,如:"./ets/widget/pages/WidgetCard.ets"。当为JS卡片时,完整路径无需包含卡片文件的后缀,如:"./js/widget/pages/WidgetCard" | 字符串 | 否 |
| uiSyntax | 表示该卡片的类型,当前支持如下两种类型:- arkts:当前卡片为ArkTS卡片。- hml:当前卡片为JS卡片。 | 字符串 | 可缺省,缺省值为hml |
| 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配置的刷新时间为准。 | 字符串 | 可缺省,缺省时不进行定点刷新。 |
| updateDuration | 表示卡片定时刷新的更新周期,单位为30分钟,取值为自然数。当取值为0时,表示该参数不生效。当取值为正整数N时,表示刷新周期为30*N分钟。> 说明:> updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。 | 数值 | 可缺省,缺省值为“0”。 |
| formConfigAbility | 表示卡片的配置跳转链接,采用URI格式。 | 字符串 | 可缺省,缺省值为空。 |
| formVisibleNotify | 标识是否允许卡片使用卡片可见性通知。 | 字符串 | 可缺省,缺省值为空。 |
| metadata | 表示卡片的自定义信息,包含customizeData数组标签。 | 对象 | 可缺省,缺省值为空。 |
示例:
{
"forms": [
{
"name": "简单卡片",
"description": "This is a service widget.",
"src": "./ets/widget1/pages/Widget1Card.ets",
"uiSyntax": "arkts",//卡片类型为arkTS
"window": {//窗口配置
"designWidth": 720,
"autoDesignWidth": true
},
"colorMode": "auto",//自适应主题样式
"isDefault": true,//是默认的卡片
"updateEnabled": true,//支持周期性刷新
"scheduledUpdateTime": "10:30",
"updateDuration": 1,//刷新周期为30*N分钟。
"defaultDimension": "2*2",
"supportDimensions": [
"2*2"
]
}
]
}
2.3 配置ability生命周期接口
| 接口 | 备注 |
|---|---|
| onAddForm(want: Want): formBindingData.FormBindingData | 卡片提供方接收创建卡片的通知接口。 |
| onCastToNormalForm(formId: string): void | 卡片提供方接收临时卡片转常态卡片的通知接口。 |
| onUpdateForm(formId: string): void | 卡片提供方接收更新卡片的通知接口。获取最新数据后调用formProvider的updateForm接口刷新卡片数据。 |
| onChangeFormVisibility(newStatus: { [key: string]: number }): void | 卡片提供方接收修改可见性的通知接口。 |
| onFormEvent(formId: string, message: string): void | 卡片提供方接收处理卡片事件的通知接口。 |
| onRemoveForm(formId: string): void | 卡片提供方接收销毁卡片的通知接口。 |
| onConfigurationUpdate(newConfig: Configuration): void | 当系统配置更新时调用。 |
| onAcquireFormState(want: Want): formInfo.FormState | 卡片提供方接收查询卡片状态通知接口。默认返回卡片初始状态。 |
2.4 开发卡片页面
与UIAbility的页面开发使用的声明范式都是一致的,但是卡片的UI与页面的UI有一定的差别。稍后做出整理。
以下表格未提及的通用事件/通用属性/UI组件/容器组件/绘制组件,表明在API9的服务卡片暂时不支持!
| 能力类型 | 能力名 | 差异点 |
|---|---|---|
| 通用事件 | 点击事件 | 无差异 |
| 挂载卸载事件 | 无差异 | |
| 通用属性 | Background | 无差异 |
| BackgroundBlurStyle | 无差异 | |
| BorderImage | 无差异 | |
| Border | 从API version 9开始,该接口支持在ArkTS卡片中使用,卡片中仅支持设置相同的边框样式/宽度/颜色/边框圆角半径。 | |
| ComponentId | 无差异 | |
| Enable | 无差异 | |
| FlexLayout | 无差异 | |
| GradientColor | 无差异 | |
| ImageEffect | 无差异 | |
| LayoutConstraints | 无差异 | |
| Location | 无差异 | |
| Opacity | 无差异 | |
| Overlay | 无差异 | |
| PolymorphicStyle | 无差异 | |
| SharpClipping | 无差异 | |
| Size | 无差异 | |
| Touch-target | 无差异 | |
| Transformation | 无差异 | |
| Visibility | 无差异 | |
| ZOrder | 无差异 | |
| 绘制组件 | Circle | 无差异 |
| Ellipse | 无差异 | |
| Line | 无差异 | |
| Path | 无差异 | |
| Polygon | 无差异 | |
| Polyline | 无差异 | |
| Rect | 无差异 | |
| Shape | 卡片中不支持使用PixelMap对象 | |
| 容器组件 | Badge | 无差异 |
| Column | 无差异 | |
| Counter | 无差异 | |
| Flex | 无差异 | |
| GridCol | 无差异 | |
| GridRow | 无差异 | |
| List | 无差异 | |
| ListItem | 无差异 | |
| RelativeContainer | 无差异 | |
| Row | 无差异 | |
| Stack | 无差异 | |
| 基础组件 | Blank | 无差异 |
| Button | 无差异 | |
| Checkbox | 无差异 | |
| CheckboxGroup | 无差异 | |
| DataPanel | 无差异 | |
| Divider | 无差异 | |
| Gauge | 无差异 | |
| Image | ● ArkTS卡片支持gif图片格式动效,但仅在显示时播放一次。● ArkTS卡片上不支持http://等网络相关路径前缀和file://路径前缀的字符串。● ArkTS卡片上不支持PixelMap类型。 | |
| LoadingProgress | 无差异 | |
| Marquee | ArkTS卡片上跑马灯循环次数设置任意值都仅在可见时滚动一次。 | |
| Progress | 无差异 | |
| Qrcode | 无差异 | |
| Radio | 无差异 | |
| Rating | 无差异 | |
| Slider | 无差异 | |
| Span | 无差异 | |
| Text | 无差异 | |
| Toggle | 无差异 | |
| 画布组件 | Canvas | 无差异 |
| Canvas绘制上下文对象 | 无差异 | |
| 渐变对象 | 无差异 | |
| ImageBitmap对象 | ArkTS卡片上不支持http://等网络相关路径前缀、datashare://路径前缀以及file://data/storage路径前缀的字符串的图片。 | |
| ImageData对象 | 无差异 | |
| Path2D对象 | 无差异 | |
| ForEach组件 | 无差异 | |
| 动画 | 属性动画 | 在ArkTS卡片上属性动画的最大动画持续时间为1000毫秒。 |
| 显式动画 | 在ArkTS卡片上最大动画持续时间为1000毫秒,若超出则固定为1000毫秒。 | |
| 组件内转场 | 无差异 | |
| 像素单位 | 无差异 | |
| 组件生命周期 | ● aboutToAppear?(): void● aboutToDisappear?(): void● onLayout?(children: Array, constraint: ConstraintSizeOptions): void● onMeasure?(children: Array, constraint: ConstraintSizeOptions): void● LayoutChild● LayoutBorderInfo● LayoutInfo | |
| 状态管理 | 无差异 |
2.5 开发卡片事件
ArkTS卡片中提供了postCardAction()接口用于卡片内部和提供方应用间的交互,当前支持router、message和call三种类型的事件,仅在卡片中可以调用。总的来说在card.ets里在事件触发时(点击/长按/触摸)调用postCardAction()接口进行与应用的交互。
接口定义:postCardAction(component: Object, action: Object): void
接口参数说明:
| 参数名 | 参数类型 | 必填 | 参数描述 |
|---|---|---|---|
| component | Object | 是 | 当前自定义组件的实例,通常传入this。 |
| action | Object | 是 | action的具体描述,详情见下表。 |
action参数说明:
| Key | Value | 样例描述 |
|---|---|---|
| "action" | string | action的类型,支持三种预定义的类型:● "router":跳转到提供方应用的指定UIAbility。● "message":自定义消息。触发后会调用提供方FormExtensionAbility的onFormEvent()生命周期回调。● "call":后台启动提供方应用。触发后会拉起提供方应用的指定UIAbility(仅支持launchType为singleton的UIAbility,即启动模式为单实例的UIAbility),但不会调度到前台。提供方应用需要具备后台运行权限(ohos.permission.KEEP_BACKGROUND_RUNNING)。 |
| "bundleName" | string | "router" / "call" 类型时跳转的包名,可选。 |
| "moduleName" | string | "router" / "call" 类型时跳转的模块名,可选。 |
| "abilityName" | string | "router" / "call" 类型时跳转的UIAbility名,必填。 |
| "params" | Object | 当前action携带的额外参数,内容使用JSON格式的键值对形式。"call"类型时需填入参数'method',且类型需要为string类型,用于触发UIAbility中对应的方法,必填。 |
router、message和call三种类型的事件适用不同的场景。
● router事件能快速拉起UIAbility到前台,如果UIAbility第一次启动,在收到Router事件后会触发onCreate生命周期回调;如果UIAbility已在后台运行,在收到Router事件后会触发onNewWant生命周期回调,需要在onWindowStageCreate方法里根据传递的targetPage不同,选择拉起不同的页面。(场景如希望点击卡片会拉应用到前台并到指定页面)文档中心
Card.ets
EntryAbility.OnCreate:
EntryAbility.OnNewWant:
EntryAbility.onWindowStageCreate:
● message事件会拉起FormExtensionAbility,然后由FormExtensionAbility刷新卡片内容,需要在onFormEvent生命周期中调用updateForm接口刷新卡片(场景如希望点击一个卡片上的按钮会刷新卡片的信息内容)文档中心
Card.ets
EntryFormAbility.onFormEvent:
在方法历调用formProvider的updateForm方法刷新数据。
● call事件能够将卡片提供方应用的指定UIAbility拉到后台。在UIAbility中接收call事件并获取参数,根据传递的method不同,执行不同的方法。其余数据可以通过readString的方式获取。需要注意的是,UIAbility需要onCreate生命周期中监听所需的方法。同时在进程退出时,需要解除监听(场景如音乐卡片,可以在卡片上提供播放/暂停)文档中心
!注意:对于后台事件一定要申请后台运行权限,否则无法使用call能力。
Card.ets
EntryAbility.事件处理函数:
EntryAbility.OnCreate里注册callee监听:
EntryAbility.OnDestory里取消监听:
● 使用router刷新卡片。这种方式需要在UIAbility的onCreate()或者onNewWant()生命周期可以通过入参want获取卡片的formID和传递过来的参数信息,然后调用formProvider的updateForm接口刷新卡片。文档中心
● 使用call事件刷新卡片。使用call事件时需要在FormExtensionAbility中的onAddForm生命周期回调中更新formId在UIAbility的onCreate生命周期中监听call事件所需的方法,然后调用updateForm接口刷新卡片。文档中心
2.6 卡片数据交互刷新
➢ 刷新分为定时刷新和定点刷新。需要在form_config.json里配置。二者定时刷新的优先级更高。
➢ 1. 定时刷新有配额限制,每张卡片每天最多通过定时方式触发刷新50次,定时刷新包含文档中心和调用setFormNextRefreshTime两种,当达到50次配额后,无法通过定时方式再次触发刷新,刷新次数会在每天的0点重置。
➢ 2. 当前定时刷新使用同一个计时器进行计时,因此卡片定时刷新的第一次刷新会有最多30分钟的偏差。比如第一张卡片A(每隔半小时刷新一次)在3点20分添加成功,定时器启动并每隔半小时触发一次事件,第二张卡片B(每隔半小时刷新一次)在3点40分添加成功,在3点50分定时器事件触发时,卡片A触发定时刷新,卡片B会在下次事件(4点20分)中才会触发。
➢ 3. 定时刷新和定点刷新仅在屏幕亮屏情况下才会触发,在灭屏场景下仅会将记录刷新动作,待亮屏时统一进行刷新。