- 首先参考创建ArkTS卡片在工程中创建动态卡片。
- 配置后台运行权限。call事件存在约束限制,卡片提供方应用需要在module.json5下添加后台运行权限。
{
"module": {
"name": "entry",
"type": "entry",
"description": "$string:module_desc",
"mainElement": "EntryAbility",
"deviceTypes": [
"phone"
],
"deliveryWithInstall": true,
"installationFree": false,
"pages": "$profile:main_pages",
"abilities": [
{
"name": "EntryAbility",
"srcEntry": "./ets/entryability/EntryAbility.ets",
"description": "$string:EntryAbility_desc",
"icon": "$media:layered_image",
"label": "$string:EntryAbility_label",
"startWindowIcon": "$media:startIcon",
"startWindowBackground": "$color:start_window_background",
"exported": true,
"skills": [
{
"entities": [
"entity.system.home"
],
"actions": [
"ohos.want.action.home"
]
}
]
}
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
"type": "backup",
"exported": false,
"metadata": [
{
"name": "ohos.extension.backup",
"resource": "$profile:backup_config"
}
],
},
{
"name": "EntryFormAbility",
"srcEntry": "./ets/entryformability/EntryFormAbility.ets",
"label": "$string:EntryFormAbility_label",
"description": "$string:EntryFormAbility_desc",
"type": "form",
"metadata": [
{
"name": "ohos.extension.form",
"resource": "$profile:form_config"
}
]
}
],
"requestPermissions":[
{
"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
}
]
}
} - 添加卡片到桌面,EntryFormAbility实现如下:
import { formBindingData, FormExtensionAbility, formInfo } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';
export default class EntryFormAbility extends FormExtensionAbility {
onAddForm(want: Want) {
if (!want || !want.parameters) {
return formBindingData.createFormBindingData('');
}
let formId: string = want.parameters[formInfo.FormParam.IDENTITY_KEY] as string;
let formData: Record<string, string> = {
'formId': formId
};
return formBindingData.createFormBindingData(formData);
}
}; - 点击卡片更新数据时,在卡片页面调用postCardAction向指定UIAbility发送call事件,并根据实际的业务需求进行传参。
let storageUpdateCall = new LocalStorage();
@Entry(storageUpdateCall)
@Component
struct WidgetExampleCard {
@LocalStorageProp('title') title: string = 'title';
@LocalStorageProp('detail') detail: string = '未更新.';
@LocalStorageProp('formId') formId: string = '';
build() {
Row() {
Column() {
Text(this.title)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.fontColor($r('sys.color.font'));
Text(this.detail)
.fontSize(14)
.fontWeight(FontWeight.Medium)
.fontColor($r('sys.color.font'));
// 卡片按钮点击事件
Button('更新数据')
.onClick(() => {
postCardAction(this, {
action: 'call',
// 只能跳转到当前应用下的UIAbility,与module.json5中定义保持一致
abilityName: 'EntryAbility',
params: {
formId: this.formId,
// 需要调用的方法名称
method: 'funA',
newData: 'new title', // 修改后的数据
detail: '已更新',
formEvent: 'DATA_CHANGE' // 自定义事件类型
}
});
});
}
.width('100%');
}
.height('100%')
.backgroundColor($r('sys.color.comp_background_primary'));
}
} - 在指定的UIAbility中监听call事件,根据监听到的method参数中的方法名称调用对应方法,并通过rpc.Parcelable获取参数,使用AppStorage进行全局的UI状态存储。
import { ConfigurationConstant, UIAbility } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { rpc } from '@kit.IPCKit';
import { formBindingData, formProvider } from '@kit.FormKit';
import { BusinessError } from '@kit.BasicServicesKit';
const DOMAIN = 0x0000;
// ipc通信返回类型的实现,用于数据序列化和反序列化
class MyParcelable implements rpc.Parcelable {
num: number;
str: string;
constructor(num: number, str: string) {
this.num = num;
this.str = str;
}
marshalling(messageSequence: rpc.MessageSequence): boolean {
messageSequence.writeInt(this.num);
messageSequence.writeString(this.str);
return true;
}
unmarshalling(messageSequence: rpc.MessageSequence): boolean {
this.num = messageSequence.readInt();
this.str = messageSequence.readString();
return true;
}
}
export default class EntryAbility extends UIAbility {
onCreate(): void {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
// 监听call事件所需的方法并调用
this.callee.on('funA', this.callUpdateFunc);
}
private callUpdateFunc = (data: rpc.MessageSequence): MyParcelable => {
let params: Record<string, string> = JSON.parse(data.readString());
if (params.formEvent === 'DATA_CHANGE') {
AppStorage.setOrCreate('title', params.newData);
AppStorage.setOrCreate('detail', params.detail);
if (params.formId !== undefined) {
// 更新卡片显示
const bindData = formBindingData.createFormBindingData({
'title': params.newData,
'detail': params.detail
});
formProvider.updateForm(params.formId, bindData).catch((err: BusinessError) => {
console.error(`更新卡片失败: ${params.formId}, ${err.code}, ${err.message}`);
});
}
}
return new MyParcelable(1, 'aaa');
};
onDestroy(): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
try {
this.callee.off('funA');
} catch (err) {
hilog.info(DOMAIN, 'testTag', '%{public}s', JSON.stringify(err));
}
}
onWindowStageCreate(windowStage: window.WindowStage): void {
// Main window is created, set main page for this ability
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
windowStage.loadContent('pages/Index', (err) => {
if (err.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
return;
}
AppStorage.setOrCreate('title', 'title');
AppStorage.setOrCreate('detail', '未更新');
hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
});
}
} - 在应用页面内使用@StorageLink对AppStorage中对应的属性建立数据同步,使页面数据同步更新。
@Entry
@Component
struct Index {
@StorageLink('title') title: string = '';
@StorageLink('detail') detail: string = '';
build() {
Column({space: 20}) {
Text(`卡片内容:${this.title}`)
.fontSize(20)
.margin(10)
Text(`描述:${this.detail}`)
.fontSize(20)
.margin(10)
}
.height('100%')
.width('100%')
.padding(20)
}
}