一、背景

在开发鸿蒙项目时,需要实现“主工程跨工程调用扫码功能”,出现以下几个坑,记录下踩坑过程;

坑:“扫码按钮无反应” → “注册服务后应用崩溃” → “依赖包引入仍报错”,最终靠版本匹配 + 配置优化解决。

二、项目情况:

2.1、项目背景

扫码功能我们是封装在一个工程模块中,目前已有一个上线的app使用了该功能,那现在新开发的app引入该模块扫码能力即可

2.2、核心需求

点击主工程 “扫码” 按钮,通过ServiceManager调用扫码服务,跳转到扫码页面

三、踩坑记录

3.1、坑1:跨工程扫码按钮无反应,控制台无报错

3.1.1、现象:

在主工程中添加扫码按钮,调用扫码模块的IAddDeviceRouterService服务跳转扫码页,但点击后无任何反应,控制台打印日志发现是undefined,无其他报错:

Text('扫码').fontColor('#ffffff')
  .onClick(()=>{
    console.log('lucy== 999',ServiceManager.getService<IAddDeviceRouterService>('IAddDeviceRouterService'))
    ServiceManager.getService<IAddDeviceRouterService>('IAddDeviceRouterService')?.toScanPage()
  })

3.1.2、过程:

一开始以为是相机权限问题,检查module.json5已配置ohos.permission.CAMERA,但仍无反应;但日志打印是undefined,意识到可能是服务未注册的原因

3.1.3、原因分析:

IAddDeviceRouterService是项目的自定义服务(非鸿蒙原生),需通过ServiceManager.registerService手动注册,主工程未执行注册逻辑,导致获取服务实例为undefinedtoScanPage()方法从未执行。

3.1.4、解决方案:在应用启动时注册服务

该服务在另一个模块方法内已经注册,引入即可

1、找到项目的bindService方法(负责服务注册),在需要使用扫码功能的工程中引入该方法;

2、在工程EntryAbility初始化时调用bindService,传递应用上下文:

// 主工程EntryManager.ts
import { bindService } from '@xxx/device-config';

export class EntryManager {
  onCreateInit(want: Want, context: common.UIAbilityContext) {
    this.context = context;
    bindService(this.context); // 注册IAddDeviceRouterService等服务
    // 其他初始化逻辑...
  }
}

3、注册逻辑(@xxx/device-config中的bindService):

@xxx/device-config是公司内部封装的基础工具模块,注册逻辑在该模块已封装,项目中引入该模块即可

// 服务注册代码
export function bindService(context:Context) {
  ServiceManager.registerService<IAddDeviceRouterService>(
    "IAddDeviceRouterService", 
    BHAddDeviceRouterService.getInstance(context)
  );
  // 其他服务注册...
}

3.2、坑 2:注册服务后应用崩溃,报错 “找不到 bdmap 模块”

3.2.1、现象:

执行服务注册后,应用启动即崩溃,日志核心报错:

Error message:cannot find record '&@bdmap/verify/Index&1.0.4',please check the request path.'/data/storage/el1/bundle/entry/ets/modules.abc'.

3.2.2、过程

1、刚开始以为是服务注册代码错误,注释IAddDeviceRouterService注册后,应用正常启动,确定是该服务依赖导致;

2、查看报错信息,发现其内部引用了@bdmap/verify/Index模块(百度地图验证组件),主工程未引入该依赖。

3.2.3、原因分析

那就说明问题不是出现服务注册代码上,问题出在百度地图依赖包没有引入的原因,导致加载服务实现类时,触发 “模块未找到” 的错误。

3.2.4、解决方案:引入@bdmap/verify私有 HAR 包

在主工程oh-package.json5中添加依赖,并npm install安装依赖

{
  "dependencies": {
    "@bdmap/verify": "1.0.4" // 版本需与已上线app版本一致
  }
}

3.3、坑 3:引入@bdmap/verify后仍崩溃,单一依赖不够

3.3.1、现象:

仅引入@bdmap/verify@1.0.4后,应用仍崩溃,报错与之前一致,无任何变化。

3.3.2、过程

1、检查@bdmap/verify包是安装正常,那就排除依赖未安装问题 

2、尝试单独引入@bdmap/verify的依赖包@bdmap/base,配置后仍报错;

3、逐一尝试引入@bdmap/map@bdmap/search等相关包,最终加全 4 个包后报错消失。

3.3.3、原因分析

@bdmap/verify@1.0.4强耦合的组合包,内部依赖 4 个配套底层包,仅引入单一依赖无法满足模块加载需求

鸿蒙编译时不会校验私有包的内部依赖,仅在运行时触发 “模块未找到” 错误,且日志不明确提示缺失哪个依赖,只能反向试错。

3.3.4、解决方案:用overrides强制统一配套版本

在主工程oh-package.json5中添加overrides配置,强制项目中所有@bdmap/*包使用与@bdmap/verify@1.0.4配套的版本:

备注:以下这几个依赖的版本是同事在开发已上线app时引入该能力发现版本太高无法编译,通过一步步调式试错才得出以下版本

{
  "overrides": {
    "@bdmap/base": "^1.2.1",
    "@bdmap/map": "^1.2.8",
    "@bdmap/search": "^1.2.8",
    "@bdmap/locsdk": "1.1.5"
  }
}

说明:官网里面根据这一场景也给了解决方法 ⬇️ 

四、避坑总结

1、跨工程服务调用:先注册,再使用

既然用了,就要找到是哪里注册的,需注册后才能用,否则返回undefined

2、私有 HAR 包依赖:版本配套是最关键

私有 HAR 包(如@bdmap/verify)常存在 “强耦合依赖”,需找到完整的配套版本组合;

overrides是强制统一所有子依赖版本,可以解决 “版本不配套导致的模块解析失败”

3、通过日志,查看问题根源

鸿蒙ARKTS 的 “cannot find record” 错误,本质是 “模块未找到 / 解析失败”,

可能原因:依赖包未安装+依赖版本不兼容+模块导出 / 导入路径错误;

排查思路:先查依赖是否完整→再查版本是否配套→最后查代码引用是否正确

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐