HarmonyOS鸿蒙Next中资源在打包后为什么id会被替换成-1

HarmonyOS鸿蒙Next中资源在打包后为什么id会被替换成-1 通过$r(‘app.string.xxxx’)引入资源,在打包后,为什么id会被替换成-1

原始代码:

cke_2513.png

打包后查看js文件:

cke_1534.png

这个导致诸如

this.getUIContext().getHostContext()?.resourceManager.getNumber($r(‘app.integer.xxxx’).id)

等方法无法在打包后正常使用


更多关于HarmonyOS鸿蒙Next中资源在打包后为什么id会被替换成-1的实战教程也可以访问 https://www.itying.com/category-93-b0.html

9 回复

开发者你好,我这边项目在进行编译的时候,并不会出现id为-1的情况,辛苦提供一下你这边的IDE版本信息,我这边进一步分析。
示例如下:

{ "id": 16777311, "type": 10003, params: [], "bundleName": "com.aaa.xxx", "moduleName": "entry" }

更多关于HarmonyOS鸿蒙Next中资源在打包后为什么id会被替换成-1的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


把这个useNormalizedOHMUrl设置为true,在编译期暴露错误。

有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html

这个其实是 HarmonyOS 资源系统的一个“运行时资源对象”机制,不是资源真的丢了。

你看到:

$r('app.string.xxx')

打包后变成:

{
  id: -1,
  type: xxxx,
  params: [...]
}

这是因为:

HarmonyOS NEXT 在:

HAR/HSP
动态资源
跨包资源

场景下,

很多 $r() 返回的已经不是:

静态编译期资源ID

而是:

Resource对象(懒加载资源引用)

所以:

id = -1

代表:

当前资源没有固定编译期resId

不是异常。

因此:

你这种写法:

resourceManager.getNumber($r('app.integer.xxx').id)

本身就不可靠。

因为:

$r()

现在不一定有真实 id。

尤其:

HarmonyOS 5+

Stage模型

HAR组件化

以后:

越来越多资源会变成动态Resource

而不是 Android 那种:

R.xxx.xxx 固定int id

正确写法(推荐)

不要依赖 .id

改成:

resourceManager.getNumberByName(...)

或者:

resourceManager.getStringByName(...)

例如:

const rm = this.getUIContext().getHostContext()?.resourceManager

let value = rm?.getNumberByName('app.integer.xxx')

这是官方更推荐的方式。

或者:

直接使用 Resource:

很多组件本身支持:

Resource

直接传:

Text($r('app.string.xxx'))

不要自己取 id。

为什么 Debug 可能正常,Release 出问题?

因为:

Debug 下:

可能保留本地资源映射

Release / HAR 后:

资源会重新编译
资源ID压缩
动态资源化

所以:

id=-1

更容易出现。

尤其你这种:

HAR包
HSP
组件库

场景,

最容易出现:

Resource.id = -1

因为资源可能根本不在当前 module。

一句话总结:

HarmonyOS NEXT 中 $r() 返回的很多已经是动态 Resource 对象,不再保证存在固定 resId,因此打包后 id=-1 是正常现象。不要再依赖 .id 去调用 resourceManager.getXXX(),应改用 getXXXByName() 或直接传递 $r() Resource 对象。

确认下是不是开启了混淆,如果开启,关掉配置中的混淆,重新打包试试~

在模块build-profile.json5配置文件中的arkOptions.obfuscation.ruleOptions字段中,通过enable字段配置是否开启混淆。

"arkOptions": {
  "obfuscation": {
    "ruleOptions": {
      "enable": false, // 关闭混淆开关。
      "files": ["./obfuscation-rules.txt"] // 指定配置混淆规则文件, 在编译本模块时生效。
    },
    // ...
  }
},

相关文档:

👍,

id变包后变成-1是因为编译器开启了混淆,要在obfuscation-rules.txt下新增配置

# 保留 ResourceTable 类中的所有字段
-keep class .*.ResourceTable {
    public <fields>;
}

# 保留所有使用 @Entry 注解的类
-keep  class  **.view.** {
    <methods>;
}

在HarmonyOS Next中,资源打包后ID被替换为-1,是因为资源编译阶段,资源索引表被重新生成,未正确注册的资源ID会被置为无效值(-1)。常见原因包括:资源文件路径或命名违反规范、资源未在resources目录下正确配置、或使用了不支持的资源类型。打包工具无法映射该资源时,即分配-1。

在 HarmonyOS NEXT 正式打包(如 Release 模式)时,编译器会启用资源 ID 压缩/混淆优化。此时 $r() 返回的 Resource 对象中的 id 字段会被统一标记为 -1,表示该 ID 不再具有直接映射到具体资源的意义,这是为了减小包体并防止反编译通过 ID 直接访问资源。
代码里 $r('app.integer.xxxx').id 因此拿到 -1,传递给 resourceManager.getNumber() 自然失败。
正确做法是直接传递整个 Resource 对象给 resourceManager API,例如 getNumber($r('app.integer.xxxx')),引擎内部会使用 Resource 中的 bundleName/moduleName 和资源名称进行解析,而非依赖打包后的 id

回到顶部