当前位置:首页>鸿蒙APP>鸿蒙元服务从开发到上架 —— “每日格言”技术分享

鸿蒙元服务从开发到上架 —— “每日格言”技术分享

  • 2026-10-11 05:41:52
鸿蒙元服务从开发到上架 —— “每日格言”技术分享

“每日格言”概述

“每日格言”是一个展示格言的元服务。每天格言不重复,感受文字带来的力量!

1. 项目详情及使用方式

通过滑动界面,可以刷新查看最新的格言;可以根据关键字来搜索格言;可以朗读格言的内容。每天格言不重复,感受文字带来的力量!

2. 项目的亮点

程序简洁容易操作;功能内聚;无需操作手册即可上手。

3. 功能界面展示

以下是“每日格言”元服务核心功能界面展示。

首页:各个功能的入口;可以根据关键字进行搜索。

详情:查看格言详情页;可以朗读格言。

“每日格言”核心技术分析

“每日格言”使用最新 HarmonyOS 6 开发。项目中涉及的关键技术:

  1. Navigation 实现页面的切换;
  2. Grid 和 Stack 实现首页布局;
  3. LazyForEach 实现数据懒加载;
  4. @Builder 装饰器自定义格言详情界面;
  5. 基于 HarmonyOS 的场景化语音服务等AI能力实现本文朗读。

1. Navigation 实现页面的切换

在主页 Index.ets 文件中,Navigation 组件用于实现页面的切换。

// 创建一个导航控制器对象并传入NavigationpageInfos: NavPathStack = new NavPathStack();build() {  Navigation(this.pageInfos) {    // ...  }  .mode(NavigationMode.Stack)  .hideTitleBar(true)}

2. Grid 和 Stack 实现首页布局

Grid 和 Stack 实现首页布局。

Stack() {  Image($r('app.media.bg'))    .objectFit(ImageFit.Fill)    .width('100%')    .height('100%')  Scroll() {    Column() {      Row() {        Search({ value: this.searchContent, placeholder: '关键字搜索...', controller: this.controller })          .searchIcon(new SymbolGlyphModifier($r('sys.symbol.magnifyingglass')).fontColor([$r('app.color.main_background')]))          .cancelButton({            style: CancelButtonStyle.CONSTANT,            icon: new SymbolGlyphModifier($r('sys.symbol.xmark')).fontColor([Color.Green])          })          .searchButton('搜索')          .width('70%')          .height(40)          .backgroundColor('#F5F5F5')          .placeholderColor(Color.Grey)          .placeholderFont({ size: 14, weight: 400 })          .textFont({ size: 14, weight: 400 })          .margin(20)          .onSubmit((value: string) => {            this.searchContent = value;            this.doSearch(this.searchContent)          })      }.width('100%')      .justifyContent(FlexAlign.Start)      Grid(this.scroller, this.layoutOptions) {        // ...      }      .columnsGap(8)      .rowsGap(8)      .columnsTemplate('1fr')      .width('100%')      .height('100%')      .padding({ left: 10, right: 10, bottom: 40 })    }    .width('100%')    .height('100%')    .margin({ bottom: 10 })  }.width('100%')  .scrollBar(BarState.Off)}

其中,Stack 的作用是将子组件堆叠起来,并设置堆叠顺序。在最底层,使用 Image 组件将背景图片填充到整个屏幕。 Grid 组件用于实现网格布局,并设置列数和列间距。

3. LazyForEach 实现数据懒加载

LazyForEach 组件用于实现数据懒加载。

Grid(this.scroller, this.layoutOptions) {  LazyForEach(this.dataSource, (item: Poet) => {    GridItem() {      // 根据数据渲染格言卡片      Text(`${item.title}(${item.author})`)        .width('100%')        .height(28)        .margin(10)        .fontColor($r('sys.color.font_primary'))        .fontSize(24)        .maxLines(1)        .textOverflow({ overflow: TextOverflow.Ellipsis })        .onClick(e => {          // 切换到Detail页面          // 将name指定的NaviDestination页面信息入栈,传递的参数为item          this.pageInfos.pushPathByName('PageDetail', item);          console.log('切换到Detail页面');        })    }  }, (item: Poet) => item.id + ''  )}

懒加载组件 LazyForEach 接收两个参数:数据源和数据渲染函数。数据源是一个数组,数据渲染函数是一个函数,用于根据数据源中的数据渲染组件。

懒加载组件会根据数据源中的数据,自动创建对应的组件。这里的组件比较简单,用 Text 组件来渲染格言卡片。

格言卡片主要是显示格言的标题和作者。

点击格言卡片,会跳转到 PageDetail 页面,并显示该格言的详情。

4. @Builder 装饰器自定义格言详情界面

@Builder 装饰器用于自定义格言详情界面。

@Builderfunction TextLineBuilder(poet: Poet, color: string, index: number) {  if (poet) {    Stack() {      Image($r('app.media.type_' + index))        .objectFit(ImageFit.Fill)        .width('100%')        .height('100%')      Column(){        Text(poet.title)          .fontSize(24)          .fontWeight(FontWeight.Bold)          .fontColor(color)          .backgroundColor(Color.White)        Text(poet.author)          .fontSize(20)          .fontWeight(FontWeight.Medium)          .fontColor(color)          .backgroundColor(Color.White)        ForEach(poet.paragraphs, (paragraph: string, index: number) => {          Text(paragraph)            .fontSize(22)            .fontWeight(FontWeight.Lighter)            .fontColor(color)            .backgroundColor(Color.White)        })      }.width('100%')      .height('100%')      .justifyContent(FlexAlign.Center)    }    .width('100%')    .height('100%')  }}

上述函数同样是使用了 Stack 布局:在最底层,使用 Image 组件将背景图片填充到整个屏幕;上层是将格言的标题、作者和内容分别放在三个 Text 组件中。

5. 场景化语音服务实现本文朗读

借助 HarmonyOS 的场景化语音服务等 AI 能力,可以轻松实现本文的朗读功能。

Button('朗读').onClick(() => {  // 初始化文章列表  this.readInfoList = [    {      id: this.poet.id + '',      title: {        text: this.poet.title,        isClickable: true      },      author: {        text: this.poet.author,        isClickable: true      },      bodyInfo: this.poet.paragraphs.join('\n')    }  ]  this.selectedReadInfo = this.readInfoList[0]  // 朗读控件执行朗读  TextReader.start(this.readInfoList, this.selectedReadInfo?.id)    .catch((error: BusinessError) => {      console.error(`start failed, code: ${error.code}, message: ${error.message}`)    })}).margin(10)

从开发到上架经验总结

本节以“每日格言”应用上架为例,记录完整的鸿蒙 HamonyOS 应用上架手动签名与发布流程。

(一)上架手动签名

HarmonyOS 应用/元服务通过数字证书( .cer 文件)和 Profile 文件( .p7b 文件)来保证应用/元服务的完整性。

在申请数字证书和 Profile 文件前,首先需要通过 DevEco Studio 来生成密钥(存储在格式为 .p12 的密钥库文件中)和证书请求文件( .csr 文件)。

然后,申请调试数字证书和调试 Profile 文件。最后,将密钥( .p12 )文件、数字证书( .cer )文件和 Profile(.p7b)文件配置到工程中。

基本概念

  1. 密钥:格式为 .p12,包含非对称加密中使用的公钥和私钥,存储在密钥库文件中,公钥和私钥对用于数字签名和验证。
  2. 证书请求文件:格式为 .csr,全称为 Certificate Signing Request,包含密钥对中的公钥和公共名称、组织名称、组织单位等信息,用于向 AppGallery Connect 申请数字证书。
  3. 数字证书:格式为 .cer,由华为 AppGallery Connect 颁发。
  4. Profile 文件:格式为 .p7b,包含 HarmonyOS 应用/元服务的包名、数字证书信息、描述应用/元服务允许申请的证书权限列表,以及允许应用/元服务调试的设备列表(如果应用/元服务类型为 Release 类型,则设备列表为空)等内容,每个应用/元服务包中均必须包含一个 Profile 文件。

1. 生成密钥文件

在 DevEco Studio 中生成密钥文件。

设置存储路径:比如本例 D:\dev\harmonyos\keystore\birlower_20250916.p12

输入密码

设置别名:比如本例 birlower_20250916

2. 生成证书请求文件

基于上一步的密钥文件,生成证书请求文件。

设置存储路径:比如本例 D:\dev\harmonyos\keystore\birlower_20250916.csr

3. 新增数字证书

登录 AppGallery Connect,点击左侧导航栏的“数字证书”,点击“新增数字证书”。

填写证书信息,并上传上一步生成的证书请求文件。

证书名称:比如本例 birlower_20250916

证书类型:发布证书

下载数字证书文件到指定目录待用。

4. 添加 Profile

点击“ Profile ”,添加 Profile。

Profile 名称:birlower_20250916

类型:发布

选择证书:选择上一步新增的数字证书

下载Profile文件到指定目录待用。

5. 手动配置签名信息

在 DevEco Studio 中配置密钥( .p12 )文件、申请的调试证书( .cer )文件和调试 Profile( .p7b )文件。

在 File > Project Structure > Project > Signing Configs 窗口中,取消勾选“ Automatically generate signature ”,然后配置工程的签名信息。

  • Store file:选择第 1 步生成的密钥库文件,文件后缀为 .p12,该文件为生成密钥和证书请求文件中生成的 .p12 文件。

  • Store password:输入第 1 步的密钥库密码,该密码与生成密钥和证书请求文件中填写的密钥库密码保持一致。

  • Key alias:输入第 1 步的密钥的别名信息,与生成密钥和证书请求文件中填写的别名保持一致。

  • Key password:输入第 1 步的密钥的密码,与生成密钥和证书请求文件中填写的 Store Password 保持一致。

  • Sign alg:签名算法,固定为 SHA256withECDSA。

  • Profile file:选择第 4 步生成的申请调试证书和调试 Profile 文件中生成的 Profile 文件,文件后缀为 .p7b。

  • Certpath file:选择第 3 步生成的申请调试证书和调试 Profile 文件中生成的数字证书文件,文件后缀为 .cer。

(二)构建软件包

打包 APP 时,DevEco Studio 会将工程目录下的所有 HAP/HSP 模块打包到 APP 中,因此,如果工程目录中存在不需要打包到 APP 的 HAP/HSP 模块,请手动删除后再进行编译构建生成 APP。

单击 Build > Build Hap(s)/APP(s) > Build APP(s),等待编译构建完成已签名的应用包。

当未指定构建模式时,构建 APP 包,默认 Release 模式;构建 HAP/HSP/HAR 包,默认 Debug 模式。即 Build APP(s) 时,默认构建的 APP 包为 Release 类型,符合上架要求,开发者无需进行另外设置。

编译构建完成后,可以在工程目录 build > outputs > default 下,获取带签名的应用包,例如“ DailyQuotesAtomicService-default-signed.app ”。

(三)上传软件包

AGC 软件包管理,选择测试和正式上架,上述上一步的软件包“ DailyQuotesAtomicService-default-signed.app ”。

(四)分发

AGC 版本信息,软件版本选择上一步的软件版本。

正确填写应用多语言信息,有助于增加应用在应用市场曝光,输入的文字会以文本方式展示,不支持 html 标签。

设置下隐私声明,建议是使用隐私声明托管。

以上就是我元服务从开发到上架的详细过程,希望对大家有所帮助。

如果大家对鸿蒙开发感兴趣,也参与到当中来,期待与你相遇。

最新文章

随机文章