文章目录这个 API 到底干什么用的项目结构第一步配置 module.json5第二步编写卡片 Ability第三步在主页调用 openFormManager第四步卡片 UI 页面Want 参数中的 dimension 值对应关系整体流程图常见坑写在最后桌面卡片用户不知道怎么添加让应用自己引导他。formProvider.openFormManager就是干这个的一行代码直接把系统的卡片管理页弹出来用户点点就加好了。这个 API 到底干什么用的正常流程是用户长按桌面图标 → 点击服务卡片 → 在列表里找到你的卡片 → 手动添加。整个操作链路又长用户又不知道在哪里找。formProvider.openFormManager允许你从应用内部主动拉起这个卡片管理页而且还能指定默认打开哪个卡片通过Want参数传递卡片名、尺寸、模块信息。用户打开你的应用点一个按钮卡片管理页自己弹出来傻瓜操作。大白话版就像你在超市里让服务员直接带你到你要的商品货架而不是自己在几千平米里瞎找。项目结构核心文件就这几个FormManagerDemo/ └── entry/src/main/ets/ ├── pages/ │ └── Index.ets ← 主页面放按钮 ├── entryformability/ │ └── EntryFormAbility.ets ← 卡片 Ability处理卡片创建 └── widget/pages/ └── WidgetCard.ets ← 卡片 UI 页面第一步配置 module.json5卡片必须在extensionAbilities里注册这是前提缺了就没法用// entry/src/main/module.json5 { module: { name: entry, type: entry, extensionAbilities: [ { name: EntryFormAbility, srcEntry: ./ets/entryformability/EntryFormAbility.ets, label: $string:widget_label, description: $string:widget_desc, type: form, // 必须是 form 类型 metadata: [ { name: ohos.extension.form, resource: $profile:form_config // 指向卡片配置文件 } ] } ] } }卡片配置文件resources/base/profile/form_config.json里要定义卡片名称{forms:[{name:widget,// 这里的 name 要跟代码里的对上displayName:$string:widget_display_name,description:$string:widget_desc,src:./js/widget/pages/WidgetCard,uiSyntax:arkts,window:{designWidth:720,autoDesignWidth:true},isDefault:true,updateEnabled:true,scheduledUpdateTime:10:30,updateDuration:1,supportDimensions:[2*2],defaultDimension:2*2}]}第二步编写卡片 Ability// entry/src/main/ets/entryformability/EntryFormAbility.etsimport{formBindingData,FormExtensionAbility,formInfo}fromkit.FormKit;import{Want}fromkit.AbilityKit;exportdefaultclassEntryFormAbilityextendsFormExtensionAbility{// 卡片被创建时调用返回初始数据onAddForm(want:Want):formBindingData.FormBindingData{constformData;returnformBindingData.createFormBindingData(formData);}onCastToNormalForm(formId:string):void{}onUpdateForm(formId:string):void{}onFormEvent(formId:string,message:string):void{}onRemoveForm(formId:string):void{}onAcquireFormState(want:Want):formInfo.FormState{returnformInfo.FormState.READY;}}第三步在主页调用 openFormManager这是核心代码Want参数里的几个 key 是固定写法一个都不能少// entry/src/main/ets/pages/Index.etsimport{formProvider}fromkit.FormKit;import{BusinessError}fromkit.BasicServicesKit;import{Want}fromkit.AbilityKit;import{promptAction}fromkit.ArkUI;import{hilog}fromkit.PerformanceAnalysisKit;constDOMAIN0x0000;EntryComponentstruct Index{build(){Row(){Column(){Button(添加卡片到桌面).width(80%).height(50).onClick((){// 构造 Want告诉系统默认选中哪个卡片constwant:Want{bundleName:com.samples.formmanagerdemo,// 你的应用包名abilityName:EntryFormAbility,// 卡片 Ability 名parameters:{// 下面三个 key 是系统定义好的固定常量ohos.extra.param.key.form_dimension:2,// 卡片尺寸2 2*2ohos.extra.param.key.form_name:widget,// 卡片名称ohos.extra.param.key.module_name:entry// 模块名},};try{// 就这一行拉起卡片管理页formProvider.openFormManager(want);}catch(error){consterrerrorasBusinessError;promptAction.openToast({message:err.message});hilog.info(DOMAIN,testTag,openFormManager failed:${err.code}${err.message});}}).margin({top:10})}.width(100%)}.height(100%).justifyContent(FlexAlign.Center)}}第四步卡片 UI 页面卡片 UI 单独跑在一个沙盒进程里用LocalStorage接收数据用postCardAction发送交互事件// entry/src/main/ets/widget/pages/WidgetCard.etsletstorage:LocalStoragenewLocalStorage();Entry(storage)Componentstruct WidgetCard{// LocalStorageProp 接收来自 FormAbility 的数据LocalStorageProp(message)title:stringHello World;readonlyactionType:stringrouter;readonlyabilityName:stringEntryAbility;readonlymessage:stringadd detail;build(){Row(){Column(){Text(this.title).fontSize(18).fontWeight(FontWeight.Medium).fontColor($r(sys.color.font))}.width(100%)}.height(100%).backgroundColor($r(sys.color.comp_background_primary)).onClick((){// 点击卡片跳转到应用postCardAction(this,{action:this.actionType,abilityName:this.abilityName,params:{message:this.message}});})}}Want 参数中的 dimension 值对应关系看代码里有个form_dimension: 2这个数字是什么意思数值对应尺寸说明11×2最小卡片22×2标准小卡片32×4宽卡片44×4大卡片61×1最小单格这个值决定卡片管理页里默认选中哪个尺寸的卡片。如果你的卡片只支持2*2传2就行。整体流程图常见坑坑1bundleName 写错了want.bundleName必须和app.json5里的bundleName完全一致大小写都不能差。写错了openFormManager会报错但系统不一定有明确提示只会弹出空的卡片管理页。坑2form_name 和配置文件里的 name 对不上want.parameters[ohos.extra.param.key.form_name]的值必须和form_config.json里forms[].name的值完全匹配否则系统找不到指定卡片会打开管理页但不会默认选中。坑3try-catch 不能省openFormManager在某些情况下比如设备不支持服务卡片、卡片未注册会同步抛出异常不套 try-catch 直接崩。坑4该 API 仅限卡片提供方调用只有应用自己卡片提供方才能调用openFormManager第三方应用不能替你拉起别的应用的卡片管理页。写在最后openFormManager是一个很小但很实用的 API。如果你的应用有服务卡片功能在合适的位置比如首次启动引导、功能介绍页加上这个入口能大幅提升卡片的添加率。毕竟用户不是开发者他们不知道长按图标有服务卡片这个选项你得主动引导。