灯光模拟HarmonyOS应用实战-75-应用级标签叫The_kemusan、Ability叫灯光模拟、首页又叫驾考助手:用ProductIdentityMatrix收口应用身份

一个 HarmonyOS 工程里可以同时出现工程目录名、bundleName、应用级标签、Ability 标签、模块描述和首页标题。它们本来服务于不同技术层,但如果没有统一产品身份,用户可能在安装信息、桌面入口和应用首页看到不同名称,测试人员也很难判断截图、包和需求是否属于同一个产品。

The_kemusan 当前就呈现了这种漂移:工程与应用级资源使用英文下划线名称,EntryAbility 标签是“灯光模拟”,首页标题是“驾考灯光综合助手”,模块描述又聚焦“科目三灯光模拟”。与此同时,首页已经覆盖科一、科二、科三和科四。解决办法不是全局搜索替换,而是先建立 ProductIdentityMatrix,为每个表面指定唯一来源、长度策略、允许差异和发布证据。

ProductIdentityMatrix应用身份封面

本文只讨论身份治理与配置接线,不擅自决定最终品牌名,也不会把源码配置当作桌面或商店已经展示的运行证据。

一、当前工程至少存在五层身份文本

AppScope/resources/base/element/string.jsonapp_nameThe_kemusanAppScope/app.json5 将应用级 label 指向它,并把 bundleName 写为 com.example.the_kemusan

{
  "app": {
    "bundleName": "com.example.the_kemusan",
    "vendor": "example",
    "versionName": "1.0.0",
    "label": "$string:app_name"
  }
}

entry 模块资源中,module_descEntryAbility_descEntryAbility_label 又是三套中文文本:

{
  "string": [
    {
      "name": "module_desc",
      "value": "科目三灯光模拟单机应用"
    },
    {
      "name": "EntryAbility_desc",
      "value": "科目三灯光模拟"
    },
    {
      "name": "EntryAbility_label",
      "value": "灯光模拟"
    }
  ]
}

首页 Index.etspageTitle 初始值和返回首页赋值均为“驾考灯光综合助手”。这些都是当前源码可读事实。不同系统表面最终选用应用 label 还是 Ability label,需要以对应 HarmonyOS 版本和安装运行结果核对,不能只看资源文件猜桌面最终文字。

二、名称差异有时合理,失去映射才危险

工程目录名适合开发工具和文件系统,bundleName 是长期技术身份,桌面标签受空间限制,首页标题可以更完整。它们没有必要逐字相同,但必须能从同一产品定义推导。

层级当前值或来源主要用途是否适合随意改动
工程目录The_kemusan本地开发定位可改,但影响脚本和路径
bundleNamecom.example.the_kemusan安装、签名与升级身份高风险,不应为改文案顺手更换
应用级 label$string:app_nameThe_kemusan应用元数据候选名称应由产品显示名管理
EntryAbility label$string:EntryAbility_label灯光模拟Ability 入口名称可短于全名,但需矩阵说明
模块与 Ability 描述科目三相关文本配置说明已与多科目首页范围不完全一致
首页标题驾考灯光综合助手应用内品牌与功能认知当前为 ArkTS 字面量

危险不在“简称”二字,而在团队不知道哪个值是主名称、哪个是受控简称、哪个只是旧工程代号。发布截图、隐私文本、商店资料和客服说明便可能各取一个名字。

三、首页能力范围已经超过单一科三描述

当前 MODULES 包含科一灯光题、科二灯光基础、科三模拟与实操、科四灯光题、题库、历史和设置。首页副标题也写着“科一 · 科二 · 科三 · 科四灯光专项”。

export const MODULES: ModuleEntry[] = [
  { id: 'subject1', title: '科一灯光题', badge: '理论' },
  { id: 'subject2', title: '科二灯光基础', badge: '基础' },
  { id: 'subject3Exam', title: '科三灯光模拟', badge: '模拟' },
  { id: 'subject3Flow', title: '科三实操灯光', badge: '实操' },
  { id: 'subject4', title: '科四灯光题', badge: '安全' },
  { id: 'questionBank', title: '题库', badge: '题库' },
  { id: 'history', title: '错题本/历史', badge: '复盘' },
  { id: 'settings', title: '设置', badge: '本机' }
];

代码摘录省略了 subtitle 字段,只用于说明能力覆盖。由此可以确认 module_desc = 科目三灯光模拟单机应用 没有完整描述当前首页范围;但最终产品应继续聚焦科三,还是升级为综合灯光助手,属于产品决策,不能由开发者根据模块数量自动决定。

应用身份从配置到用户表面的流转

四、ProductIdentityMatrix先记录表面与规则

矩阵的第一版可以是可审阅配置,列出稳定产品 ID、主显示名、短名、工程代号、技术身份和各表面绑定。它不存签名口令或证书路径。

export interface ProductIdentityMatrix {
  productId: string;
  canonicalDisplayName: ResourceStr;
  shortDisplayName: ResourceStr;
  homeTitle: ResourceStr;
  productDescription: ResourceStr;
  engineeringCodename: string;
  bundleName: string;
  identityVersion: number;
}

export const PRODUCT_IDENTITY: ProductIdentityMatrix = {
  productId: 'driving-light-practice',
  canonicalDisplayName: $r('app.string.product_name'),
  shortDisplayName: $r('app.string.product_short_name'),
  homeTitle: $r('app.string.product_home_title'),
  productDescription: $r('app.string.product_description'),
  engineeringCodename: 'The_kemusan',
  bundleName: 'com.example.the_kemusan',
  identityVersion: 1
};

示例中的中文资源值刻意没有给出,因为当前资料没有产品方确认的唯一品牌。engineeringCodename 可以保留旧工程名,只要它不继续流入用户可见表面。bundleName 是现状记录,不代表示例建议该值适合正式发布;是否变更要结合签名、升级和商店应用身份单独评估。

五、给每个表面建立绑定,不靠人工记忆

矩阵还需要一张表面绑定清单。这样审核者能看到“为什么桌面是短名而首页是全名”,而不是在多个 JSON 和 ArkTS 文件之间猜。

type IdentitySurface =
  | 'app-label'
  | 'entry-ability-label'
  | 'module-description'
  | 'ability-description'
  | 'home-title'
  | 'about-title'
  | 'store-display-name';

interface IdentityBinding {
  surface: IdentitySurface;
  sourceKey: string;
  maxLength: number;
  mayUseShortName: boolean;
  releaseEvidence: string;
}

const IDENTITY_BINDINGS: IdentityBinding[] = [
  {
    surface: 'entry-ability-label',
    sourceKey: 'product_short_name',
    maxLength: 8,
    mayUseShortName: true,
    releaseEvidence: 'installed-launcher-capture'
  },
  {
    surface: 'home-title',
    sourceKey: 'product_home_title',
    maxLength: 16,
    mayUseShortName: false,
    releaseEvidence: 'home-page-capture'
  }
];

长度只是产品约束示例,应按实际桌面布局、字体和多端窗口调整。releaseEvidence 说明接受该表面需要什么材料;源文件存在只能证明配置,不等于安装后显示正确。

六、用户可见文字统一进入资源层

产品身份矩阵、资源与消费层结构

首页标题现在是 @State pageTitle: string = '驾考灯光综合助手'goHome() 又写了一次同样字面量。建议先把主标题和模块描述搬到资源文件,再让配置和页面引用受控键。

{
  "string": [
    {
      "name": "product_name",
      "value": "待产品确认的完整名称"
    },
    {
      "name": "product_short_name",
      "value": "待确认短名"
    },
    {
      "name": "product_home_title",
      "value": "待确认首页标题"
    },
    {
      "name": "product_description",
      "value": "待确认产品范围描述"
    }
  ]
}

上面的“待确认”只能用于评审分支,不能进入最终包。正式值确认后,AppScope 与 entry 模块能否直接共享同一资源键要按资源归属和工程构建规则安排;不要为了复用创建含义相同却值独立的两份副本。

页面标题如果需要随模块变化,可以把首页默认标题和子页标题分开:默认值来自 product_home_title,进入模块后来自模块目录,返回首页只恢复资源引用。这样全局品牌与功能页标题不会互相覆盖。

七、配置修改要遵循外到内的依赖顺序

身份收口涉及配置和 UI,建议按以下顺序实施:先确认主名和短名;再更新资源;然后更新 app.json5module.json5 绑定;最后替换页面字面量和外围资料。每一步都要保留 bundleName 的独立决策。

// AppScope/app.json5
{
  "app": {
    "bundleName": "com.example.the_kemusan",
    "label": "$string:product_name"
  }
}

// entry/src/main/module.json5
{
  "module": {
    "description": "$string:product_description",
    "abilities": [
      {
        "name": "EntryAbility",
        "label": "$string:product_short_name"
      }
    ]
  }
}

这段展示目标绑定关系,不是当前文件原文。更新时应保留 module 中现有页面、图标、启动窗口、skills 和备份扩展配置,不能为了改名称重写整个 JSON5。

八、自动审计要找漂移,不替产品选名字

可以写一个很小的审计脚本,读取矩阵和配置,核对每个用户表面是否绑定了允许的资源键。脚本不判断“驾考助手”和“灯光模拟”哪个更好,只判断是否偏离已批准矩阵。

interface IdentityObservation {
  surface: IdentitySurface;
  configuredKey: string;
  configuredValue: string;
}

function auditIdentity(
  bindings: IdentityBinding[],
  observations: IdentityObservation[]
): string[] {
  const issues: string[] = [];
  for (let index = 0; index < bindings.length; index++) {
    const binding = bindings[index];
    const current = findObservation(
      observations,
      binding.surface
    );
    if (current === undefined) {
      issues.push('MISSING_SURFACE:' + binding.surface);
      continue;
    }
    if (current.configuredKey !== binding.sourceKey) {
      issues.push('WRONG_SOURCE:' + binding.surface);
    }
  }
  return issues;
}

审计还应扫描首页标题、关于页、隐私说明和导出文件名中的旧用户可见名称。工程目录、包名、源码注释和历史迁移键可以列入允许保留清单,避免盲目全局替换破坏兼容性。

九、发布证据要分配置、产物和实际表面

同一个名称需要三层证据。源文件层证明资源和引用已修改;构建产物层证明资源进入目标包;安装表面层证明桌面、最近任务、首页和系统设置中的实际文字符合矩阵。

interface IdentityEvidence {
  identityVersion: number;
  sourceBindingsPassed: boolean;
  artifactMetadataPassed: boolean;
  launcherObserved: boolean;
  homeObserved: boolean;
  settingsObserved: boolean;
}

function isIdentityAccepted(evidence: IdentityEvidence): boolean {
  return evidence.sourceBindingsPassed &&
    evidence.artifactMetadataPassed &&
    evidence.launcherObserved &&
    evidence.homeObserved &&
    evidence.settingsObserved;
}

如果当前任务只做了源码变更,就只报告 sourceBindingsPassed。构建成功也不能替代桌面和系统设置页观察;模拟器截图也不能自动升级为真机、多尺寸和商店审核证据。

名称变化还要核对无障碍播报、通知来源、分享文本、备份恢复说明和隐私政策主体。当前工程是否拥有这些表面要以实际模块和发布资料为准,不应为了填满矩阵凭空新增。

十、排障表、验证清单与事实边界

现象优先核对常见原因处理方向
源码改了,桌面仍是旧名应用与 Ability 两级 label只改其中一个资源按矩阵检查实际入口引用
首页新名,系统设置仍是英文名AppScope 应用 label只替换 ArkTS 字面量更新应用级资源与绑定
改名后旧版本无法覆盖安装bundleName 与签名身份把显示名改造扩大到技术身份回退 bundleName,单独评估迁移
模块描述仍只写科三产品范围与资源源头描述未随能力范围评审由产品确认后统一资源
不同语言下又出现两套品牌资源键与翻译约束译者把短名当普通文案标记品牌键并审阅各语种
截图里的名称互相矛盾证据对应版本混用了不同包或旧截图记录 identityVersion 和包版本
全局替换破坏路径或历史键允许保留清单把工程代号与显示名混为一类只替换用户表面绑定
  • 产品方确认完整名称、短名、首页标题和范围描述。
  • 工程代号、bundleName 与用户显示名被明确区分。
  • app_name、Ability label、模块描述和首页标题都有矩阵绑定。
  • 首页不再重复写死同一个品牌字面量。
  • 名称修改没有顺手改变 bundleName、签名或数据键。
  • 科一至科四的当前能力范围已反映在批准描述中。
  • 多语言资源把品牌键作为受控内容审阅。
  • 审计脚本能够发现错误资源键和遗漏表面。
  • 源码、产物、桌面、系统设置和首页证据分别记录。
  • 截图、日志和报告都标注应用版本与 identityVersion。

当前源码能够确认:工程目录与应用级 app_name 使用 The_kemusan;bundleName 是 com.example.the_kemusan;entry 的 Ability 标签是“灯光模拟”;模块与 Ability 描述聚焦科三;首页标题是“驾考灯光综合助手”;主页能力已经覆盖科一到科四。系统桌面最终显示哪个标签、该应用是否已上架以及外部资料使用什么名称,都没有在本文中验证。

ProductIdentityMatrix、表面绑定、资源键和审计脚本都是建议方案,尚未写入当前工程。本文没有执行构建,没有生成 HAP,也没有在模拟器或真机核对桌面、最近任务、设置页和首页显示。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐