HarmonyOS鸿蒙Next中用@Sendable注释的类再打包har时怎么编写混淆规则?

HarmonyOS鸿蒙Next中用@Sendable注释的类再打包har时怎么编写混淆规则? cke_512.png

在混淆的

-keep-property-name
-keep-global-name

中配置了类名和属性名后,集成时报错Error message:Cannot add property in prevent extensions。


更多关于HarmonyOS鸿蒙Next中用@Sendable注释的类再打包har时怎么编写混淆规则?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

尊敬的开发者您好,我这边配置了混淆且开启 -keep-property-name 、 -keep-global-name规则,entry包引用har包@Sendable注释的类,并未复现到您的问题,可以正常构建运行。

您这边是否方便提供一下您的复现代码以便我们定位分析具体原因。

更多关于HarmonyOS鸿蒙Next中用@Sendable注释的类再打包har时怎么编写混淆规则?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


问题核心分析

[@Sendable](/user/Sendable) 是鸿蒙(HarmonyOS)中用于标记可跨线程安全传递的类 / 接口的注解,打包 HAR(鸿蒙归档包)时混淆该类,核心问题是:

  1. [@Sendable](/user/Sendable) 类的属性 / 方法被混淆后,鸿蒙运行时无法识别其跨线程安全特性;
  2. Cannot add property in prevent extensions 报错本质是:混淆规则破坏了类的「不可扩展(prevent extensions)」特性([@Sendable](/user/Sendable) 类默认被标记为不可动态扩展属性),导致运行时尝试添加属性失败。

正确的混淆规则编写(针对 @Sendable 类)

1. 核心混淆规则模板(proguard-rules.pro

# 1. 保留[@Sendable](/user/Sendable)注解本身(关键)
-keep @ohos.annotation.Sendable class * {*;}

# 2. 保留目标[@Sendable](/user/Sendable)类的完整结构(类名、所有属性、方法,不混淆)
# 替换为你的[@Sendable](/user/Sendable)类全路径(支持通配符*)
-keep class com.xxx.your.SendableClass {
    <fields>;      # 保留所有属性
    <methods>;     # 保留所有方法
    <init>();      # 保留所有构造方法
}

# 3. 禁止混淆该类的属性名/方法名(全局保留)
# 若用-keep-property-name-keep-global-name,需仅保留该类的属性,而非全局
-keep-property-name-keep-global-name class com.xxx.your.SendableClass {
    *;
}

# 4. 关键:禁止对该类执行「prevent extensions」相关混淆(解决核心报错)
-dontoptimize class com.xxx.your.SendableClass
-dontshrink class com.xxx.your.SendableClass
-dontwarn com.xxx.your.SendableClass

# 5. 若该类实现了特定接口/继承父类,需同步保留
-keep class com.xxx.your.SendableClass implements com.xxx.ParentInterface {*;}

2. 错误规则修正(你之前的问题)

你报错的核心原因是:-keep-property-name-keep-global-name 配置了全局属性保留,而非仅目标 [@Sendable](/user/Sendable) 类,导致其他类的属性也被强制保留,触发「不可扩展类添加属性」冲突。

✅ 修正前(错误):

# 错误:全局保留所有类的属性名,导致冲突
-keep-property-name-keep-global-name * {*;}

✅ 修正后(正确):

# 仅保留[@Sendable](/user/Sendable)类的属性名
-keep-property-name-keep-global-name class com.xxx.your.SendableClass {*;}

关键规则解释

规则项 作用 为什么必须加
-keep @ohos.annotation.Sendable class * {*;} 保留所有带 @Sendable 注解的类结构 鸿蒙运行时依赖该注解识别跨线程安全类,混淆后注解失效会触发安全检查错误
<fields>; / <methods>; 保留类的所有属性 / 方法 @Sendable 类的属性 / 方法被混淆后,跨线程传递时会因反射找不到属性而报错
-dontoptimize/-dontshrink 禁止优化 / 收缩该类 混淆工具的「代码优化」可能会移除类的空方法 / 属性,或修改类的可扩展特性,触发「prevent extensions」报错
精准指定类路径 避免全局保留导致冲突 全局保留属性名会让其他不可扩展类被强制添加属性,触发核心报错

额外注意事项(必看)

  1. HAR 包混淆的特殊要求

    • HAR 包的混淆规则需在 build-profile.json5 中明确指定:
      {
        "apiType": "stageMode",
        "buildOption": {
          "proguard": {
            "enable": true,
            "rules": ["proguard-rules.pro"] // 指向你的混淆规则文件
          }
        }
      }
      
  2. 避免过度混淆

    • [@Sendable](/user/Sendable) 类通常用于跨线程通信,其属性 / 方法名必须与调用方(如 UI 线程、后台线程)保持一致,绝对不能混淆名称
    • 若该类有内部类,需同步保留内部类结构:
      -keep class com.xxx.your.SendableClass$* {*;}
      
  3. 报错验证

    • 配置完规则后,先执行 gradlew clean assembleHar 打包 HAR,检查是否有混淆警告;
    • 集成 HAR 后,运行时若仍报错,需检查:
      • 类是否被误标记为 sealed/final(不可扩展);
      • 是否有动态代码(如反射)修改该类属性。

总结

  1. 核心规则:必须保留[@Sendable](/user/Sendable)注解本身 + 目标类的完整结构(类名、属性、方法),禁止全局保留属性名,仅精准保留目标类;
  2. 报错根源-keep-property-name-keep-global-name 全局配置导致不可扩展类被强制添加属性,需缩小保留范围到目标[@Sendable](/user/Sendable)类;
  3. 关键配置:添加-dontoptimize/-dontshrink禁止对该类优化,避免破坏「不可扩展」特性。

在HarmonyOS鸿蒙Next中,对使用@Sendable注释的类编写混淆规则时,需要在混淆配置文件中使用-keep规则保留这些类及其公共API。具体可配置为:-keep @ohos.hiviewdfx.Sendable class * { *; },以确保序列化相关的类成员不被混淆。

在HarmonyOS Next中,@Sendable注解用于标记可以在不同线程间安全传递的类。当包含此类代码的模块被打包成HAR(Harmony Archive)时,如果混淆规则配置不当,确实会遇到Cannot add property in prevent extensions这类错误。

这个错误通常是由于混淆规则过于宽泛或与@Sendable类的序列化/反序列化机制冲突导致的。@Sendable类在跨线程传递时,系统需要能够正确地序列化和重建对象实例。如果混淆了关键的类名、方法名或属性名,就可能破坏这一过程。

针对你的情况,正确的混淆规则配置应聚焦于保持@Sendable类的完整结构。建议在proguard-rules.pro文件中使用以下规则:

# 保持被@Sendable注解标记的类及其公共成员不被混淆
-keep @ohos.utils.Sendable class * {
    public <fields>;
    public <methods>;
}

# 可选:如果该类有特定的序列化方法(如writeToParcel, readFromParcel),也需要保持
-keepclassmembers class * extends ohos.utils.Sendable {
    public void writeToParcel(ohos.utils.Parcel, int);
    public void readFromParcel(ohos.utils.Parcel);
}

关键点说明:

  1. 避免使用-keep-property-name-keep-global-name:你问题中使用的这些规则可能并非标准ProGuard选项,或者过于宽泛,容易导致与系统内部扩展机制的冲突,从而引发Cannot add property in prevent extensions错误。
  2. 精确保持:使用-keep @ohos.utils.Sendable class *可以精确地保留所有被@Sendable注解标记的类。内部的public <fields>;public <methods>;确保了其公共API的完整性,这对于跨线程通信至关重要。
  3. 检查继承链:如果@Sendable类继承了其他类或实现了接口,确保相关的父类或接口也在混淆规则中得到适当的保持(例如使用-keep class * implements ohos.utils.Sendable),以避免因继承链断裂而导致的运行时错误。

请用上述推荐的规则替换你项目中可能存在的过于宽泛或错误的规则,然后重新编译打包HAR。这应该能解决你遇到的集成错误。

回到顶部