灯光模拟HarmonyOS应用实战-75-应用级标签叫The_kemusan、Ability叫灯光模拟、首页又叫驾考助手:用ProductIdentityMatrix收口应用身份
灯光模拟HarmonyOS应用实战-75-应用级标签叫The_kemusan、Ability叫灯光模拟、首页又叫驾考助手:用ProductIdentityMatrix收口应用身份
一个 HarmonyOS 工程里可以同时出现工程目录名、bundleName、应用级标签、Ability 标签、模块描述和首页标题。它们本来服务于不同技术层,但如果没有统一产品身份,用户可能在安装信息、桌面入口和应用首页看到不同名称,测试人员也很难判断截图、包和需求是否属于同一个产品。
The_kemusan 当前就呈现了这种漂移:工程与应用级资源使用英文下划线名称,EntryAbility 标签是“灯光模拟”,首页标题是“驾考灯光综合助手”,模块描述又聚焦“科目三灯光模拟”。与此同时,首页已经覆盖科一、科二、科三和科四。解决办法不是全局搜索替换,而是先建立 ProductIdentityMatrix,为每个表面指定唯一来源、长度策略、允许差异和发布证据。

本文只讨论身份治理与配置接线,不擅自决定最终品牌名,也不会把源码配置当作桌面或商店已经展示的运行证据。
一、当前工程至少存在五层身份文本
AppScope/resources/base/element/string.json 的 app_name 是 The_kemusan。AppScope/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_desc、EntryAbility_desc 和 EntryAbility_label 又是三套中文文本:
{
"string": [
{
"name": "module_desc",
"value": "科目三灯光模拟单机应用"
},
{
"name": "EntryAbility_desc",
"value": "科目三灯光模拟"
},
{
"name": "EntryAbility_label",
"value": "灯光模拟"
}
]
}
首页 Index.ets 的 pageTitle 初始值和返回首页赋值均为“驾考灯光综合助手”。这些都是当前源码可读事实。不同系统表面最终选用应用 label 还是 Ability label,需要以对应 HarmonyOS 版本和安装运行结果核对,不能只看资源文件猜桌面最终文字。
二、名称差异有时合理,失去映射才危险
工程目录名适合开发工具和文件系统,bundleName 是长期技术身份,桌面标签受空间限制,首页标题可以更完整。它们没有必要逐字相同,但必须能从同一产品定义推导。
| 层级 | 当前值或来源 | 主要用途 | 是否适合随意改动 |
|---|---|---|---|
| 工程目录 | The_kemusan | 本地开发定位 | 可改,但影响脚本和路径 |
| bundleName | com.example.the_kemusan | 安装、签名与升级身份 | 高风险,不应为改文案顺手更换 |
| 应用级 label | $string:app_name → The_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.json5、module.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,也没有在模拟器或真机核对桌面、最近任务、设置页和首页显示。
更多推荐


所有评论(0)