鸿蒙应用内添加服务卡片到桌面:formProvider.openFormManager 实战

复制代码
# 鸿蒙应用内添加服务卡片到桌面:formProvider.openFormManager 实战

## 一、背景

传统上,用户要添加鸿蒙服务卡片到桌面,需要长按桌面空白处 → 选择服务卡片 → 翻找目标应用 → 添加到桌面。这个路径对于普通用户来说不够直观,很多用户甚至不知道服务卡片的存在。

HarmonyOS 从 API version 18 开始提供了 `formProvider.openFormManager()` 方法,允许**在应用内直接拉起卡片管理页面**,用户只需点击「添加至桌面」即可完成操作。本文以新华字典应用为例,详细介绍这一功能的实现。

---

## 二、效果预览

用户在应用中点击标题栏右侧的 **➕** 按钮 → 系统弹出卡片管理页面 → 点击「添加至桌面」→ 桌面出现新华字典服务卡片,点击卡片即可打开应用。

```
┌──────────────────────┐     ┌──────────────────────┐
│ 新华字典        [➕]  │     │  卡片管理页面          │
│                      │  →  │                      │
│  [🔍 请输入汉字...]   │     │  ┌────────────────┐  │
│                      │     │  │ 📖 新华字典     │  │
│   查询结果...         │     │  │ [添加至桌面]     │  │
│                      │     │  └────────────────┘  │
└──────────────────────┘     └──────────────────────┘
```

---

## 三、开发环境

| 工具 | 版本 |
|------|------|
| OpenHarmony SDK | 23(API 11) |
| 目标设备 | HarmonyOS 6.1.0 |
| 开发语言 | ArkTS |

> **注意**:`formProvider.openFormManager()` 从 API 18 开始可用。API 11 版本同样支持,但实际效果取决于设备系统版本。

---

## 四、实现步骤

### 4.1 添加依赖导入

在页面文件中导入所需模块:

```typescript
import { formProvider } from '@kit.FormKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
import { Want } from '@kit.AbilityKit';
```

各模块的作用:

| 模块 | 用途 |
|------|------|
| `@kit.FormKit` | `formProvider` 提供 `openFormManager` 方法 |
| `@kit.BasicServicesKit` | `BusinessError` 用于错误类型判断 |
| `@kit.ArkUI` | `promptAction` 用于 Toast 提示 |
| `@kit.AbilityKit` | `Want` 定义跳转目标 |

### 4.2 实现 openFormManager 方法

```typescript
/**
 * 打开卡片管理页面,将服务卡片添加到桌面
 */
openFormManager(): void {
  const want: Want = {
    bundleName: 'com.nutpi.myapplication',
    abilityName: 'DictionaryFormAbility',
    parameters: {
      'ohos.extra.param.key.form_dimension': 2,
      'ohos.extra.param.key.form_name': 'DictionaryForm',
      'ohos.extra.param.key.module_name': 'entry'
    },
  };
  try {
    formProvider.openFormManager(want);
  } catch (error) {
    promptAction.openToast({
      message: (error as BusinessError).message
    });
  }
}
```

### 4.3 Want 参数详解

| 参数 | 值 | 说明 |
|------|-----|------|
| `bundleName` | `com.nutpi.myapplication` | 应用的包名,与 `AppScope/app.json5` 中的 `bundleName` 一致 |
| `abilityName` | `DictionaryFormAbility` | FormExtensionAbility 的名称,与 `module.json5` 中注册的名称一致 |
| parameters.`form_dimension` | `2` | 默认卡片尺寸(1=1×2,2=2×2) |
| parameters.`form_name` | `DictionaryForm` | 卡片名称,与 `form_config.json` 中的 `name` 一致 |
| parameters.`module_name` | `entry` | 模块名 |

### 4.4 添加 UI 入口

在标题栏添加一个按钮,触发 `openFormManager`:

```typescript
Row() {
  Text('新华字典')
    .fontSize(22)
    .fontWeight(FontWeight.Bold)
    .fontColor('#1a1a2e')
    .layoutWeight(1)

  // 添加到桌面按钮
  Button() {
    Text('➕').fontSize(16)
  }
  .width(40)
  .height(40)
  .borderRadius(20)
  .backgroundColor('#f0f0f5')
  .margin({ right: 16 })
  .onClick(() => {
    this.openFormManager();
  })
}
```

---

## 五、完整代码

```typescript
import { queryWord } from '../utils/WordApi';
import { WordItemData } from '../model/WordData';
import { formProvider } from '@kit.FormKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
import { Want } from '@kit.AbilityKit';

@Entry
@Component
struct Index {
  @State searchWord: string = '';
  @State wordData: WordItemData | null = null;
  @State isLoading: boolean = false;
  @State errorMsg: string = '';

  build() {
    Column() {
      Row() {
        Text('新华字典')
          .fontSize(22)
          .fontWeight(FontWeight.Bold)
          .fontColor('#1a1a2e')
          .layoutWeight(1)

        Button() {
          Text('➕').fontSize(16)
        }
        .width(40).height(40).borderRadius(20)
        .backgroundColor('#f0f0f5')
        .margin({ right: 16 })
        .onClick(() => { this.openFormManager(); })
      }
      .width('100%')
      .padding({ top: 16, bottom: 8, left: 20 })

      // ... 搜索和结果 UI ...
    }
  }

  openFormManager(): void {
    const want: Want = {
      bundleName: 'com.nutpi.myapplication',
      abilityName: 'DictionaryFormAbility',
      parameters: {
        'ohos.extra.param.key.form_dimension': 2,
        'ohos.extra.param.key.form_name': 'DictionaryForm',
        'ohos.extra.param.key.module_name': 'entry'
      },
    };
    try {
      formProvider.openFormManager(want);
    } catch (error) {
      promptAction.openToast({
        message: (error as BusinessError).message
      });
    }
  }
}
```

---

## 六、前置条件:卡片必须已正确配置

`openFormManager` 能够正确工作的前提是**服务卡片已经正确配置**。确保以下几点:

### 6.1 form_config.json 存在且正确

```json
{
  "forms": [{
    "name": "DictionaryForm",
    "displayName": "新华字典",
    "src": "./ets/form/FormWidget.ets",
    "uiSyntax": "arkts",
    "updateEnabled": true,
    "defaultDimension": "1*2",
    "supportDimensions": ["1*2", "2*2"]
  }]
}
```

### 6.2 FormExtensionAbility 已注册

在 `module.json5` 中:

```json5
{
  "extensionAbilities": [{
    "name": "DictionaryFormAbility",
    "srcEntry": "./ets/form/FormAbility.ets",
    "type": "form",
    "exported": true,
    "metadata": [{
      "name": "ohos.extension.form",
      "resource": "$profile:form_config"
    }]
  }]
}
```

### 6.3 卡片名称保持一致

以下三个位置的卡片名称必须完全一致:

| 位置 | 字段 |
|------|------|
| `form_config.json` | `name: "DictionaryForm"` |
| `module.json5` | `name: "DictionaryFormAbility"` |
| `openFormManager` 参数 | `form_name: "DictionaryForm"` |

---

## 七、常见问题

### Q1:点击按钮后无反应?

**检查项**:
1. `form_config.json` 是否存在且格式正确
2. `module.json5` 中 FormExtensionAbility 的 `type: "form"` 和 `metadata` 配置是否正确
3. `openFormManager` 的 `bundleName` 是否与 `app.json5` 中的一致

### Q2:提示「未找到卡片信息」?

**可能原因**:`form_name` 与 `form_config.json` 中的 `name` 不一致。

**解决**:确保两个地方完全匹配。

### Q3:卡片管理页面空白?

**可能原因**:设备系统版本过低,不支持此 API。

**解决**:在 API 18+ 的设备上测试。低版本设备需要改用传统方式(桌面长按添加)。

---

## 八、用户体验建议

1. **加个引导**:首次打开应用时,可以通过弹窗提示用户「添加到桌面,快速查询」
2. **位置显眼**:按钮放在标题栏等用户容易注意到的位置
3. **加个 Toast 反馈**:添加成功或失败时给用户明确的反馈(已用 try-catch + promptAction 实现)
4. **配合使用教程**:可以做一个简单的引导页面,教会用户如何使用卡片

---

## 九、总结

`formProvider.openFormManager()` 是提升鸿蒙服务卡片使用率的利器。通过在应用内提供「添加到桌面」入口,用户可以更便捷地发现和使用服务卡片功能。

核心要点:
- 三步走:导入模块 → 配置 Want → 调用 `openFormManager`
- 三个名称必须一致:`form_config.json` / `module.json5` / `openFormManager` 参数
- 三个前提条件:form_config 存在 / FormExtensionAbility 注册 / 卡片名称匹配

---

## 项目地址

本文所有代码已开源:[https://gitcode.com/jianguoxu/myapplication](https://gitcode.com/jianguoxu/myapplication)
相关推荐
不爱吃糖的程序媛1 小时前
hionic框架设备信息获取:@ionic-native/device 插件在鸿蒙PC平台的适配实践
华为·harmonyos
小雨下雨的雨1 小时前
鸿蒙PC用Electron框架——Canvas蜡笔抖动效果实现技术深度解析
前端·javascript·华为·electron·鸿蒙系统
tigershang2 小时前
华为“韬定律”:从“缩小尺寸”到“压缩时间”——后摩尔时代的规则重塑
单片机·华为·系统架构
小雨下雨的雨2 小时前
蜡笔小画家鸿蒙PC用Electron框架 - 儿童学画蜡笔画技术实现详解
前端·javascript·华为·electron·前端框架·交互·鸿蒙系统
坚果的博客2 小时前
【鸿蒙 PC三方库构建系统】README.OpenSource 文件深度解读
华为·开源·harmonyos
川石课堂软件测试2 小时前
什么是埋点测试,app埋点测试怎么做?
功能测试·测试工具·华为·小程序·单元测试·appium·harmonyos
Swift社区2 小时前
鸿蒙 App 状态管理:实现原理 + 最佳实践
华为·harmonyos
网络与设备以及操作系统学习使用者2 小时前
多路由设备静态路由配置详解
运维·网络·学习·华为·智能路由器
IT大白鼠2 小时前
GRE协议原理与华为设备配置实践
网络·网络协议·华为