尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

HarmonyOS Stage模型module.json5配置解析:从入门到避坑

HarmonyOS Stage模型module.json5配置解析:从入门到避坑 1. 先搞清楚module.json5在Stage模型中管什么事做鸿蒙应用开发第一步不是写界面而是把工程的骨架搭明白。你在DevEco Studio里新建一个工程默认就是Stage模型同时会自动生成一大批配置文件。很多新手一上来看到好几个json5文件就懵了分不清哪个管什么最后连包名都去module.json5里找找半天找不到。这里先把格局打开。Stage模型从API 9开始成为HarmonyOS应用开发的主推模型它把整个应用的配置体系拆成了两层应用级配置和模块级配置。应用级配置放在AppScope/app.json5里描述的是整个应用包的属性比如包名、版本号、应用图标。模块级配置就是每个模块module里的module.json5描述的是这个模块自己的完整信息包括模块名、模块类型、支持的设备、入口Ability、权限声明等。你可以把app.json5理解成公司的营业执照module.json5则是某个部门的工作手册。营业执照登记的是公司的统一社会信用代码和经营范围工作手册记录的则是这个部门的人员构成、分工安排和对外接口。一个应用可能会包含多个模块每个模块都有自己的module.json5它们合在一起才构成完整的应用。module.json5在Stage模型里承担的核心职责可以概括成三件事声明这个模块是什么name、type、description声明这个模块能跑在什么设备上、从哪个页面启动deviceTypes、mainElement、pages声明这个模块需要哪些系统权限、对外暴露哪些能力requestPermissions、abilities说得更直白一点模块能不能编译通过、能不能安装到真机、能不能上架应用市场、应用启动时能不能找到入口页面全部都由module.json5说了算。它的重要性一点不亚于业务代码但恰恰因为是配置很多人不太当回事等到打包上架或者真机调试时才被各种异常卡住回头排查才发现就是配置文件里的一个小字段写错了。这篇文章我打算把module.json5从头到尾拆一遍结合实际工程配置来讲清楚每个字段的含义和坑点最后给出一份完整的避坑清单。不管你是刚接触Stage模型的新手还是从FA模型迁过来的老开发照着这篇文章走一遍配置文件这块基本就能通透。2. 核心字段逐个拆解这些配置项决定应用能否跑起来2.1 module基础块name和type先搞清楚别把entry和feature搞混module.json5最外层是一个叫module的对象里面第一个要关注的就是name和type。module.name是模块名默认工程里是entry。这个名字在同一应用的所有模块中必须唯一它会被用于HAP包命名工程里还会用这个名字来做模块间依赖和引用。如果你把entry改成myapp记得同步检查build-profile.json5里的引用关系否则可能出现模块找不到的编译错误。module.type只有两种取值entry和feature。entry是应用的主入口模块一个应用有且只能有一个entryfeature是功能模块可以根据需要增加多个。这两种类型的模块最终打出来的包都叫HAP但entry模块会被安装到设备上作为整个应用的启动入口feature模块通常用于按需加载的原子化服务或功能拆包。这里要特别提醒一个容易踩的坑module.type跟工程里常见的har、hsp不是一回事。har是静态共享包hsp是动态共享包它们对应的是构建产物类型不会出现在module.json5的type字段里。type字段只负责描述模块在应用运行时的角色定位看到type为entry就知道这是主入口模块。除了name和typemodule这一层还有description、icon和label。description通常用资源索引引用比如$string:module_desc目的是支持多语言不建议直接写死中文字符串。icon和label如果要在桌面上展示应用的名称和图标一般是配在abilities里的入口Ability上module层的icon和label更多是兜底性质。2.2 deviceTypes一个数组决定你的应用在哪些设备上被看见deviceTypes应该是module.json5里最容易被忽略、影响却最直接的字段之一。它决定了当前模块能够运行在哪些设备形态上。我在实际开发中见过不少例子开发者在模版里删掉了tablet、2in1这些设备类型只留下phone结果内部分发的测试包在平板上怎么也装不上报错信息也没明说设备不匹配。其实原因很简单——deviceTypes里没声明tablet系统在安装时就直接拒绝了。常见设备类型的取值大概是这些设备类型说明phone手机tablet平板2in1二合一设备比如笔记本/平板变形本tv智慧屏wearable智能手表等穿戴设备car车机如果你的应用打算做多设备协同或者大屏适配deviceTypes这里要跟产品形态保持一致。还有一个经验不能光在module.json5里填了设备类型就完事开发调试时真机的系统版本、API等级也必须和工程的compileSdkVersion兼容否则还是可能安装失败。2.3 mainElement和pages应用启动时首先要找的入口mainElement字段指定的是模块的入口Ability名称它必须跟abilities数组里某个ability的name完全一致。系统在拉起应用的时候会先读这个字段找到入口Ability然后创建UIAbility实例加载页面。pages字段用于指定页面路由配置文件典型写法是$profile:main_pages。它引用的是src/main/resources/base/profile/main_pages.json文件里面通过src数组声明了模块里的所有页面路径。这里有个新手的常见误区以为在main_pages.json里加页面只是为了Previewer预览或者觉得不写也能跑。事实上只要是希望通过路由框架跳转的页面都必须在这个文件里登记否则运行时会报page not found之类的错误。main_pages.json的基本结构是这样{ src: [ pages/Index, pages/DetailPage ] }每次新增页面文件记得同步更新这个列表。项目大了以后这个文件会越来越长比较推荐的做法是保持页面命名规范按照模块分组排列减少重复排查的难度。2.4 abilities数组UIAbility的关键配置逐一说明abilities是module.json5里最复杂也最核心的数组每一个元素描述一个Ability。在Stage模型里开发者在代码中继承UIAbility并实现的类对应到配置文件就是一个ability对象。一个典型的ability配置大概长这样{ name: EntryAbility, srcEntry: ./ets/entryability/EntryAbility.ts, description: $string:EntryAbility_desc, icon: $media:layered_image, label: $string:EntryAbility_label, startWindowIcon: $media:startIcon, startWindowBackground: $color:start_window_background, exported: true, skills: [ { entities: [entity.system.home], actions: [action.system.home] } ] }逐项拆开说nameAbility的类名代码里export default class EntryAbility extends UIAbility对应的类名必须跟这里的name一致。srcEntryAbility源码的相对路径注意写法以./ets/...开头。路径写错的话编译期可能不报错但运行时启动Activity会直接白屏或崩溃。descriptionAbility的描述信息建议走资源索引。icon和label图标和名称。Home图标和桌面显示名称都是从这里读取的。startWindowIcon和startWindowBackground应用启动时冷启动窗口的图标和背景色。冷启动画面这些配置其实很有讲究如果启动窗口背景色没有设置应用启动那一下可能会有白屏闪烁。exported决定这个Ability能否被其他应用拉起。入口Ability一般设为true像某些内部页面或仅供自己调用的Ability建议设为false减少外部非法调用风险。skillsintent过滤规则用于声明当前Ability能响应的动作和实体。入口Ability通常配置entity.system.home和action.system.home表示它是桌面入口。还有一些进阶属性比如launchTypesingleton、standard、specified、orientation屏幕方向、backgroundModes后台任务类型等按业务需要配置即可。如果你希望同一个Ability以单实例模式运行launchType要设成singleton否则每次打开都会创建新实例状态管理和页面返回逻辑都会变得很难搞。2.5 requestPermissions权限声明不做好动态授权就是空谈HarmonyOS的权限模型分两类system_grant和user_grant。system_grant权限在安装时由系统自动授予不用代码申请user_grant权限则是敏感权限需要在运行时动态申请申请前必须在module.json5里声明。举例来说访问网络的权限ohos.permission.INTERNET属于system_grant直接在requestPermissions里声明就行不需要额外代码而相机权限ohos.permission.CAMERA、定位权限ohos.permission.LOCATION属于user_grant除了在配置文件里声明还需要在代码里调用权限请求接口弹窗让用户授权。这里有一个关键点user_grant类权限在module.json5里的声明信息比如reason申请原因、usedScene使用场景在上架审核时会重点检查。reason建议使用资源引用描述得具体一点比如用于扫描二维码添加好友就比获取相机权限更容易通过审核。usedScene里要填写真实的调用场景不要写的很宽泛。{ name: ohos.permission.CAMERA, reason: $string:camera_reason, usedScene: { abilities: [EntryAbility], when: inuse } }记住一个原则module.json5里只声明你确实要用到的权限。多申请权限不仅影响用户体验在上架审核时也可能被质询。3. 实战配置手写一个能正常安装运行的entry模块配置这东西光看不练是不行的。这一节我把一个典型的Stage模型entry模块的module.json5从头到尾串一遍你可以直接拿去做对比和参考。3.1 标准工程自动生成的module.json5长什么样使用DevEco Studio新建一个Empty Ability工程它会自动创建如下所示的module.json5{ module: { name: entry, type: entry, description: $string:module_desc, mainElement: EntryAbility, deviceTypes: [phone, tablet], deliveryWithInstall: true, installationFree: false, pages: $profile:main_pages, abilities: [ { name: EntryAbility, srcEntry: ./ets/entryability/EntryAbility.ts, description: $string:EntryAbility_desc, icon: $media:layered_image, label: $string:EntryAbility_label, startWindowIcon: $media:startIcon, startWindowBackground: $color:start_window_background, exported: true, skills: [ { entities: [entity.system.home], actions: [action.system.home] } ] } ] } }如果你在自己工程里打开文件发现长得很像说明就是一个标准模板。模板代码是能直接跑的但通常都不满足真实业务的需求。比如很多应用需要访问网络你就得手动在module对象里补上requestPermissions。3.2 按业务需求扩展配置项假设现在我要做一个带登录页和首页的新闻应用需要网络权限还要能拉起相机拍照发图。那么除了模板自带的字段我需要做这几件事第一在module对象里增加requestPermissions数组声明网络和相机权限。网络权限是system_grant直接声明即可相机权限是user_grant需要配置reason和usedScene。第二新增一个页面的话要去resources/base/profile/main_pages.json里补路径。假设我新增了一个LoginPagesrc数组就要变成{ src: [ pages/Index, pages/LoginPage ] }第三如果我还想让应用支持平板横屏展示可以在abilities数组里给EntryAbility配置orientation或者直接依赖父级方向。但要注意平板和手机的交互形态不同盲目适配横屏反而会让页面布局崩掉这块要单独做适配。3.3 多模块场景下的配置差异真实项目不会只有一个entry模块。当你的工程里同时存在entry和feature模块时每个模块的module.json5配置会有些差异。feature模块的type字段当然是feature同时它一般不会配置skills入口也不会设置mainElement因为它是被entry或者其他模块拉起的。deviceTypes要跟entry保持一致否则会出现主模块支持手机、功能模块不支持手机这种诡异的组合编译能过但上架或者安装时会出问题。多个模块之间如果存在依赖关系比如feature模块依赖entry模块中的某个公共类这种依赖不是写在module.json5里的而是在build-profile.json5里用dependencies字段配置。3.4 改完配置文件后记得做这两件事配置文件不是改了就能立刻生效的。我在调接口或者改工程结构时经常发现改完module.json5后直接Run行为还是旧配置要么是签名不一致要么是缓存没刷新。遇到这种问题先做两件事第一在DevEco Studio菜单栏点击File Sync and Refresh Project强制同步工程配置。这一步很多时候能解决莫名其妙的构建问题。第二如果还不行Build Clean Project然后重新Build。尤其是改动过deviceTypes、abilities这类跟包结构强相关的字段clean之后再跑成功率会高很多。4. 避坑手册我踩过的module.json5配置错误实录4.1 常见报错与处理速查表我把这几年开发和答疑过程中遇到的高频配置问题整理成一个表建议收藏一下报错或现象大概率原因解决方案安装失败提示device type mismatchdeviceTypes未包含当前设备类型在module.json5的deviceTypes中加入对应设备取值启动应用白屏或直接退出abilities里srcEntry路径错误或mainElement与abilities的name不一致核对srcEntry路径、mainElement拼写路由跳转报错找不到页面页面未在main_pages.json中注册补齐页面路径权限申请后被系统拒绝权限名称拼错或未在requestPermissions中声明对照官方权限列表核对名称并声明上架审核提示权限声明不充分user_grant权限缺少reason或usedScene按实际使用场景补充完整桌面图标显示默认图标EntryAbility的icon配置错误或资源缺失检查$media资源路径模块类型相关编译错误一个应用中出现多个entry模块将新增模块type改为feature这些错误最麻烦的地方在于很多都不是编译期直接报错而是运行到某个时机才爆发。尤其是权限和设备类型编译毫无问题真机一跑就露馅。4.2 几个印象深刻的排查案例第一个是权限名拼错的问题。有一回我配置需要读取设备信息手动敲了一个ohos.permission.DEVICE_INFO看着很合理编译也没报错。结果运行时权限回调一直返回perm denied查了很久才发现官方权限名是ohos.permission.GET_DEVICE_INFO一个是DEVICE_INFO一个是GET_DEVICE_INFO。这种问题靠肉眼很难发现我的建议是把权限名统一复制官方文档里的原文不要手敲。第二个是mainElement设置成英文没问题、改成中文后应用打不开。后来发现是abilities数组里某个name不小心改成了中文而mainElement还指向原来的英文名两者匹配不上。配置文件是严格大小写和值匹配的因此改Ability名时务必同步检查mainElement和其他引用位置。第三个是路径前缀问题。srcEntry的写法是./ets/entryability/EntryAbility.ts我见过有人写成ets/entryability/EntryAbility.ts或者/ets/entryability/EntryAbility.ts少了点或者多了斜杠编译期都不一定报错但是真机上能力加载失败。这类问题排查起来最费神配置写完最好肉眼逐字符过一遍。4.3 关于自动签名和多设备调试的额外提醒在真机调试时DevEco Studio会自动配置签名但签名文件跟应用包名、模块名是有绑定关系的。如果你大改了module.json5里的模块名或者动了app.json5里的bundleName旧的自动签名可能失效需要清理后重新签名。另外如果你的设备列表里既有一台手机又有一台平板在改完deviceTypes后记得把两台设备都重新连接一遍有时候DevEco Studio缓存了旧签名信息新设备连上来反而装不上重启DevEco Studio往往是最快的解决办法。5. 与周边配置的联动app.json5和build-profile.json5的配合module.json5不是孤立存在的它跟app.json5、build-profile.json5之间存在明确的协作关系。理解这种关系配置起来才不会被绕晕。5.1 三级配置各自管什么HarmonyOS工程的配置体系大致可以分成三级配置文件位置主要职责app.json5AppScope/app.json5应用级配置包名bundleName、版本号、应用图标、应用名称module.json5各模块/src/main/module.json5模块配置模块类型、设备类型、Ability、权限、页面入口build-profile.json5根目录及各模块目录构建配置签名、编译SDK版本、模块依赖关系常有人跑到module.json5里找bundleName找半天找不到。bundleName是应用包名在app.json5里全局唯一跟具体模块无关。在签名的bin文件、上架信息、多模块协作时都会用到它。build-profile.json5决定的是这个工程怎么被构建出来包括签名使用的证书、编译的targetSdkVersion、模块之间的依赖关系。module.json5决定的是构建出来的HAP在运行时怎么表现。两者职责不同但联动紧密。你改了bundleName签名必须重新生成你改了模块依赖关系必须在build-profile.json5里同步配置module.json5管不到这个层面。5.2 新增模块时配置文件如何协同如果你在工程里新增一个feature模块DevEco Studio通常会自动生成一套模块配置包括新的module.json5、对应的build-profile.json5同时在根目录的build-profile.json5的modules数组里注册新模块。如果你手动创建目录而不是通过IDE就容易漏掉注册导致模块无法参与构建。feature模块的module.json5有几个字段需要特别检查。type字段必须更改为featuredeviceTypes建议跟entry保持一致如果该模块需要被entry模块在代码中依赖还需要在entry模块的build-profile.json5中增加依赖项我还见过一种情况工程师手动拷贝了一个HAP模块的目录改成新模块名结果漏了改module.json5里的name导致两个模块同名构建时报duplicate module。这种事后排查成本很高建议创建模块一律走IDE向导不要手工复制目录。5.3 团队协作中的配置规范建议配置文件在团队协作中容易被低估但一旦出现冲突非常折腾。根据我的经验几个小规范就能省很多事一是module.json5要纳入Code Review范围凡是改动Ability名、权限、设备类型、入口页面的都要重点review。二是权限声明遵循最小化原则不要为了省事把各种权限一次性全配上。三是描述字段尽量用字符串资源引用不要硬编码中文或英文文案方便多语言和后续维护。四是如果有多环境打包需求比如测试包和正式包需要不同包名或权限可以在构建层面对配置做动态替换但不要把多环境的逻辑堆在module.json5里写死否则上架前手工改配置容易出事。6. 最后再分享一个实用小技巧如果团队里多人维护同一个鸿蒙工程建议在工程根目录的.gitignore里忽略自动签名相关文件同时把module.json5和app.json5的改动记录纳入必须评审的范围。我在实际项目中正因为没在意这个出现了两次满屏无头绪的构建失败最后定位都是配置被不小心修改或合并冲突导致的。另外排查配置问题有个笨办法但很管用新建一个空工程对比它生成的module.json5和你有问题的module.json5逐字段diff。这个操作帮我解决过不少隐蔽问题因为标准模板里的路径、写法、大小写都是经过验证的做diff能最快缩小范围。module.json5虽然只是一个小小的配置文件但它连接了代码、构建、签名、安装、上架整个链路说它是Stage模型下应用开发的关卡文件一点都不夸张。把它彻底理解了你的鸿蒙开发路上会少掉很多莫名其妙的坑。
返回列表