@buaa_smat/hometrans 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +141 -124
- package/agents/build-fixer.md +1 -0
- package/agents/code-review-fix.md +1 -0
- package/agents/code-reviewer.md +1 -0
- package/agents/logic-coding.md +1 -0
- package/agents/logic-context-builder.md +1 -0
- package/agents/review-fixer.md +1 -0
- package/agents/self-test-fixer.md +1 -0
- package/agents/self-tester.md +260 -233
- package/agents/spec-generator.md +1 -0
- package/agents/test-tools/autotest/README.md +223 -0
- package/agents/test-tools/autotest/config.yaml.example +58 -0
- package/agents/test-tools/autotest/pyproject.toml +16 -0
- package/agents/test-tools/autotest/report_tool.py +759 -0
- package/agents/test-tools/autotest/self_test_runner.py +773 -0
- package/agents/test-tools/autotest/testcases_schema.md +143 -0
- package/agents/test-tools/autotest/testcases_tool.py +215 -0
- package/agents/test-tools/autotest/uv.lock +3156 -0
- package/agents/test-tools/harmony_autotest-0.1.0-py3-none-any.whl +0 -0
- package/agents/test-tools/hypium-6.1.0.210-py3-none-any.whl +0 -0
- package/agents/test-tools/hypium_mcp-0.6.5-py3-none-any.whl +0 -0
- package/agents/test-tools/xdevice-6.1.0.210-py3-none-any.whl +0 -0
- package/agents/test-tools/xdevice_devicetest-6.1.0.210-py3-none-any.whl +0 -0
- package/agents/test-tools/xdevice_ohos-6.1.0.210-py3-none-any.whl +0 -0
- package/dist/cli/config-store.js +27 -2
- package/dist/cli/config.js +17 -6
- package/dist/cli/index.js +3 -2
- package/dist/cli/init.js +135 -22
- package/dist/cli/mcp.js +2 -2
- package/dist/context/index.js +165 -69
- package/package.json +59 -60
- package/skills/code-dev-review-fix/SKILL.md +279 -0
- package/skills/code-dev-review-fix-workspace/evals/evals.json +56 -0
- package/skills/code-dev-review-fix-workspace/iteration-1/routing-results.md +23 -0
- package/skills/convert_pipeline/SKILL.md +423 -439
- package/skills/hmos-resources-convert/SKILL.md +623 -0
- package/skills/hmos-resources-convert/evals/evals.json +171 -0
- package/skills/hmos-resources-convert/references/conversion-rules.md +663 -0
- package/skills/hmos-resources-convert/references/dependency-analysis-rules.md +388 -0
- package/skills/hmos-resources-convert/references/resource-mapping-rules.md +457 -0
- package/skills/hmos-resources-convert/references/xml-drawable-to-svg-rules.md +513 -0
- package/skills/hmos-resources-convert/template/AppScope/app.json5 +10 -0
- package/skills/hmos-resources-convert/template/AppScope/resources/base/element/string.json +8 -0
- package/skills/hmos-resources-convert/template/AppScope/resources/base/media/background.png +0 -0
- package/skills/hmos-resources-convert/template/AppScope/resources/base/media/foreground.png +0 -0
- package/skills/hmos-resources-convert/template/AppScope/resources/base/media/layered_image.json +7 -0
- package/skills/hmos-resources-convert/template/build-profile.json5 +42 -0
- package/skills/hmos-resources-convert/template/code-linter.json5 +32 -0
- package/skills/hmos-resources-convert/template/entry/build-profile.json5 +33 -0
- package/skills/hmos-resources-convert/template/entry/hvigorfile.ts +6 -0
- package/skills/hmos-resources-convert/template/entry/obfuscation-rules.txt +23 -0
- package/skills/hmos-resources-convert/template/entry/oh-package.json5 +10 -0
- package/skills/hmos-resources-convert/template/entry/src/main/ets/entryability/EntryAbility.ets +48 -0
- package/skills/hmos-resources-convert/template/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +16 -0
- package/skills/hmos-resources-convert/template/entry/src/main/ets/pages/Index.ets +23 -0
- package/skills/hmos-resources-convert/template/entry/src/main/module.json5 +55 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/color.json +8 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/float.json +8 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/element/string.json +16 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/background.png +0 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/foreground.png +0 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/layered_image.json +7 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/media/startIcon.png +0 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/profile/backup_config.json +3 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/base/profile/main_pages.json +5 -0
- package/skills/hmos-resources-convert/template/entry/src/main/resources/dark/element/color.json +8 -0
- package/skills/hmos-resources-convert/template/entry/src/mock/mock-config.json5 +2 -0
- package/skills/hmos-resources-convert/template/entry/src/ohosTest/ets/test/Ability.test.ets +35 -0
- package/skills/hmos-resources-convert/template/entry/src/ohosTest/ets/test/List.test.ets +5 -0
- package/skills/hmos-resources-convert/template/entry/src/ohosTest/module.json5 +16 -0
- package/skills/hmos-resources-convert/template/entry/src/test/List.test.ets +5 -0
- package/skills/hmos-resources-convert/template/entry/src/test/LocalUnit.test.ets +33 -0
- package/skills/hmos-resources-convert/template/hvigor/hvigor-config.json5 +23 -0
- package/skills/hmos-resources-convert/template/hvigorfile.ts +6 -0
- package/skills/hmos-resources-convert/template/oh-package-lock.json5 +28 -0
- package/skills/hmos-resources-convert/template/oh-package.json5 +10 -0
- package/skills/hmos-resources-convert/tools/apktool.bat +85 -0
- package/skills/hmos-resources-convert/tools/apktool_3.0.1.jar +0 -0
- package/skills/hmos-ui-align/SKILL.md +182 -0
- package/skills/hmos-ui-align/config-example.json +11 -0
- package/skills/hmos-ui-align/config.json +11 -0
- package/skills/hmos-ui-align/diff_analysis.md +53 -0
- package/skills/hmos-ui-align/page_align.md +62 -0
- package/skills/hmos-ui-align/readme.md +231 -0
- package/skills/hmos-ui-align/references/Comparison_Template.md +2 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2089 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +903 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/MVVM/346/250/241/345/274/217V1.md +911 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +355 -0
- package/skills/hmos-ui-align/references/MVVM/345/274/200/345/217/221/346/226/207/346/241/243//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -0
- package/skills/hmos-ui-align/references/UI_Analysis_Template.md +4 -0
- package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2535 -0
- package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
- package/skills/hmos-ui-align/references/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
- package/skills/hmos-ui-align/scripts/app_feature_verify.py +443 -0
- package/skills/hmos-ui-align/scripts/navigation-capure.md +37 -0
- package/skills/hmos-ui-align/scripts/page_capture.py +592 -0
- package/skills/hmos-ui-align-batch/SKILL.md +99 -0
- package/skills/hmos-ui-align-batch/references/conversion-procedure.md +180 -0
- package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-atomic-component-mapping-reference.md +2535 -0
- package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-interaction-mapping-reference.md +555 -0
- package/skills/hmos-ui-align-batch/references/mappings/android-to-harmonyOS-ui-layout-mapping-reference.md +117 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Link/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/217/214/345/220/221/345/220/214/346/255/245.md +648 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Observed/350/243/205/351/245/260/345/231/250/345/222/214@ObjectLink/350/243/205/351/245/260/345/231/250/357/274/232/345/265/214/345/245/227/347/261/273/345/257/271/350/261/241/345/261/236/346/200/247/345/217/230/345/214/226.md +2089 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Prop/350/243/205/351/245/260/345/231/250/357/274/232/347/210/266/345/255/220/345/215/225/345/220/221/345/220/214/346/255/245.md +1033 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Provide/350/243/205/351/245/260/345/231/250/345/222/214@Consume/350/243/205/351/245/260/345/231/250/357/274/232/344/270/216/345/220/216/344/273/243/347/273/204/344/273/266/345/217/214/345/220/221/345/220/214/346/255/245.md +1183 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@State/350/243/205/351/245/260/345/231/250/357/274/232/347/273/204/344/273/266/345/206/205/347/212/266/346/200/201.md +576 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Track/350/243/205/351/245/260/345/231/250/357/274/232class/345/257/271/350/261/241/345/261/236/346/200/247/347/272/247/346/233/264/346/226/260.md +297 -0
- package/skills/hmos-ui-align-batch/references/mvvm/@Watch/350/243/205/351/245/260/345/231/250/357/274/232/347/212/266/346/200/201/345/217/230/351/207/217/346/233/264/346/224/271/351/200/232/347/237/245.md +395 -0
- package/skills/hmos-ui-align-batch/references/mvvm/AppStorage/357/274/232/345/272/224/347/224/250/345/205/250/345/261/200/347/232/204UI/347/212/266/346/200/201/345/255/230/345/202/250.md +903 -0
- package/skills/hmos-ui-align-batch/references/mvvm/Environment/357/274/232/350/256/276/345/244/207/347/216/257/345/242/203/346/237/245/350/257/242.md +106 -0
- package/skills/hmos-ui-align-batch/references/mvvm/LocalStorage/357/274/232/351/241/265/351/235/242/347/272/247UI/347/212/266/346/200/201/345/255/230/345/202/250.md +1178 -0
- package/skills/hmos-ui-align-batch/references/mvvm/MVVM/346/250/241/345/274/217/357/274/210V1/357/274/211.md +911 -0
- package/skills/hmos-ui-align-batch/references/mvvm/PersistentStorage/357/274/232/346/214/201/344/271/205/345/214/226/345/255/230/345/202/250UI/347/212/266/346/200/201.md +355 -0
- package/skills/hmos-ui-align-batch/references/mvvm//347/256/241/347/220/206/345/272/224/347/224/250/346/213/245/346/234/211/347/232/204/347/212/266/346/200/201/346/246/202/350/277/260.md +11 -0
- package/skills/hmos-ui-align-batch/scripts/android_parse_fast.py +1606 -0
- package/skills/self-test/SKILL.md +369 -0
- package/skills/self-test/readme.md +309 -0
- package/skills/spec-generator-skill/SKILL.md +332 -0
- package/skills/spec-generator-skill/references/android-platform-tokens.md +105 -0
- package/skills/spec-generator-skill/references/spec-sample-1.md +78 -0
- package/skills/spec-generator-skill/references/spec-sample-2.md +58 -0
- package/skills/spec-generator-skill/references/spec-sample-3.md +116 -0
- package/skills/spec-generator-skill/references/step4-report-template.md +33 -0
- package/agents/self-test-setup.md +0 -165
- package/dist/context/resources/sdkConfig.json +0 -24
- package/src/context/resources/sdkConfig.json +0 -24
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
# Android to HarmonyOS Resource Conversion Rules
|
|
2
|
+
|
|
3
|
+
This document contains the complete, detailed rules for converting Android resources to HarmonyOS format. Read this before performing any conversions. When producing the dedicated mapping markdown at `resource_mapping_path`, also read `references/resource-mapping-rules.md` — every conversion outcome described here must be reflected there as inventory rows and mapping rows.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
1. [Android Resource Directory Structure](#android-resource-directory-structure)
|
|
7
|
+
2. [HarmonyOS Resource Directory Structure](#harmonyos-resource-directory-structure)
|
|
8
|
+
3. [Values XML to Element JSON Conversion](#values-xml-to-element-json-conversion)
|
|
9
|
+
4. [Media Resource Conversion](#media-resource-conversion)
|
|
10
|
+
5. [Qualifier Mapping](#qualifier-mapping)
|
|
11
|
+
6. [Special Cases and Edge Cases](#special-cases-and-edge-cases)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Android Resource Directory Structure
|
|
16
|
+
|
|
17
|
+
Android resources live under `app/src/main/res/`. Common subdirectories:
|
|
18
|
+
|
|
19
|
+
| Directory | Contents |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `drawable/` | Images (PNG, JPG, GIF, WEBP, BMP) and XML drawables (shapes, selectors, layer-lists, vector drawables) |
|
|
22
|
+
| `drawable-<qualifier>/` | Qualified drawable variants (e.g., `drawable-hdpi`, `drawable-night`) |
|
|
23
|
+
| `mipmap/` | Launcher icons (usually at multiple densities) |
|
|
24
|
+
| `mipmap-<qualifier>/` | Qualified launcher icon variants |
|
|
25
|
+
| `values/` | XML files defining strings, colors, dimensions, styles, themes, arrays, etc. |
|
|
26
|
+
| `values-<qualifier>/` | Qualified value variants (e.g., `values-ar`, `values-zh-rCN`, `values-night`) |
|
|
27
|
+
| `layout/` | XML layout definitions |
|
|
28
|
+
| `anim/` | Tween animation XML |
|
|
29
|
+
| `animator/` | Property animation XML |
|
|
30
|
+
| `color/` | Color state list XML |
|
|
31
|
+
| `menu/` | Menu definition XML |
|
|
32
|
+
| `raw/` | Arbitrary files copied as-is |
|
|
33
|
+
| `xml/` | Arbitrary XML files (preferences, configs, etc.) |
|
|
34
|
+
| `font/` | Font files (TTF, OTF, TTC) |
|
|
35
|
+
| `transition/` | Transition animation XML |
|
|
36
|
+
| `interpolator/` | Animation interpolator XML |
|
|
37
|
+
|
|
38
|
+
## HarmonyOS Resource Directory Structure
|
|
39
|
+
|
|
40
|
+
HarmonyOS resources live under `entry/src/main/resources/`. Structure:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
resources/
|
|
44
|
+
├── base/ # Default resources
|
|
45
|
+
│ ├── element/ # Key-value resources (JSON)
|
|
46
|
+
│ │ ├── string.json
|
|
47
|
+
│ │ ├── color.json
|
|
48
|
+
│ │ ├── float.json
|
|
49
|
+
│ │ ├── integer.json
|
|
50
|
+
│ │ ├── boolean.json
|
|
51
|
+
│ │ ├── plural.json
|
|
52
|
+
│ │ ├── strarray.json
|
|
53
|
+
│ │ └── intarray.json
|
|
54
|
+
│ ├── media/ # Images, audio, video
|
|
55
|
+
│ │ ├── icon.png
|
|
56
|
+
│ │ └── ...
|
|
57
|
+
│ └── profile/ # JSON configuration files
|
|
58
|
+
│ └── ...
|
|
59
|
+
├── <qualifier>/ # Qualified resources (e.g., zh_CN, dark, ldpi)
|
|
60
|
+
│ ├── element/
|
|
61
|
+
│ ├── media/
|
|
62
|
+
│ └── profile/
|
|
63
|
+
├── rawfile/ # Raw files (accessed by path)
|
|
64
|
+
└── resfile/ # Raw files (decompressed to sandbox)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Mapping Output Requirements
|
|
68
|
+
|
|
69
|
+
In addition to performing the actual conversion, record enough metadata to later write the markdown at `resource_mapping_path`.
|
|
70
|
+
|
|
71
|
+
### Required recording behavior
|
|
72
|
+
|
|
73
|
+
- Every Android resource observed during conversion must create an Android resource inventory record.
|
|
74
|
+
- Every conversion outcome must create at least one mapping record.
|
|
75
|
+
- If a resource is skipped, unmappable, resolved as a system resource, treated as a library-only resource, or identified as a runtime remote resource, it still must be recorded.
|
|
76
|
+
- For `values/*.xml`, record inventory and mapping rows at entry granularity using `file_path#tag/name`.
|
|
77
|
+
|
|
78
|
+
### Recording examples
|
|
79
|
+
|
|
80
|
+
- `res/drawable/icon.png` copied directly → inventory row + mapping row with `mapping_kind = direct copy`
|
|
81
|
+
- `res/drawable/ic_back.xml` converted to SVG → inventory row + mapping row with `mapping_kind = svg conversion`
|
|
82
|
+
- `res/mipmap-anydpi-v26/ic_launcher.xml` converted to layered-image JSON and a generated background PNG → one inventory row + multiple mapping rows
|
|
83
|
+
- `res/layout/activity_main.xml` not converted → inventory row + mapping row with `HarmonyOS Target = N/A`
|
|
84
|
+
|
|
85
|
+
### Many-to-one and one-to-many rules
|
|
86
|
+
|
|
87
|
+
- Many Android `values` entries may land in the same HarmonyOS JSON file. Still emit one mapping row per Android source entry.
|
|
88
|
+
- One Android source may generate multiple HarmonyOS targets. Emit one mapping row per target.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
### strings.xml → string.json
|
|
94
|
+
|
|
95
|
+
**Android format:**
|
|
96
|
+
```xml
|
|
97
|
+
<resources>
|
|
98
|
+
<string name="app_name">My App</string>
|
|
99
|
+
<string name="greeting">Hello, %1$s! You have %2$d messages.</string>
|
|
100
|
+
<string name="with_apostrophe">It\'s a test</string>
|
|
101
|
+
<string name="with_html"><![CDATA[<b>Bold</b> text]]></string>
|
|
102
|
+
</resources>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**HarmonyOS format:**
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"string": [
|
|
109
|
+
{
|
|
110
|
+
"name": "app_name",
|
|
111
|
+
"value": "My App"
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"name": "greeting",
|
|
115
|
+
"value": "Hello, %1$s! You have %2$d messages."
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"name": "with_apostrophe",
|
|
119
|
+
"value": "It's a test"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"name": "with_html",
|
|
123
|
+
"value": "<b>Bold</b> text"
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Rules:**
|
|
130
|
+
- Remove Android escape sequences: `\'` → `'`, `\"` → `"`
|
|
131
|
+
- Decode XML entities: `&` → `&`, `<` → `<`, `>` → `>`, `"` → `"`, `'` → `'`
|
|
132
|
+
- Extract text from CDATA sections
|
|
133
|
+
- Preserve format placeholders (`%1$s`, `%2$d`, etc.) — HarmonyOS uses the same format
|
|
134
|
+
- If the string value is wrapped in quotes in Android XML (`"some text"`), remove the outer quotes
|
|
135
|
+
- Skip `<string>` elements with `translatable="false"` attribute? No — still include them, as they may be used at runtime. But note the translatable status.
|
|
136
|
+
|
|
137
|
+
### colors.xml → color.json
|
|
138
|
+
|
|
139
|
+
**Android format:**
|
|
140
|
+
```xml
|
|
141
|
+
<resources>
|
|
142
|
+
<color name="primary">#FF6200EE</color>
|
|
143
|
+
<color name="background">#FFFFFF</color>
|
|
144
|
+
<color name="semi_transparent">#80000000</color>
|
|
145
|
+
<color name="shorthand">#F00</color>
|
|
146
|
+
</resources>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**HarmonyOS format:**
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"color": [
|
|
153
|
+
{
|
|
154
|
+
"name": "primary",
|
|
155
|
+
"value": "#FF6200EE"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name": "background",
|
|
159
|
+
"value": "#ffFFFFFF"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"name": "semi_transparent",
|
|
163
|
+
"value": "#80000000"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"name": "shorthand",
|
|
167
|
+
"value": "#ffFF0000"
|
|
168
|
+
}
|
|
169
|
+
]
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Rules:**
|
|
174
|
+
- `#AARRGGBB` (8 digits) → keep as-is (HarmonyOS uses same format: first 2 = opacity)
|
|
175
|
+
- `#RRGGBB` (6 digits) → prepend `ff` → `#ffRRGGBB`
|
|
176
|
+
- `#ARGB` (4 digits) → expand each: `#8F00` → `#88FF0000`
|
|
177
|
+
- `#RGB` (3 digits) → expand each and add `ff`: `#F00` → `#ffFF0000`
|
|
178
|
+
- Color values are case-insensitive in Android; preserve original case or normalize
|
|
179
|
+
|
|
180
|
+
### dimens.xml → float.json
|
|
181
|
+
|
|
182
|
+
**Android format:**
|
|
183
|
+
```xml
|
|
184
|
+
<resources>
|
|
185
|
+
<dimen name="text_size">16sp</dimen>
|
|
186
|
+
<dimen name="margin_large">24dp</dimen>
|
|
187
|
+
<dimen name="border_width">1px</dimen>
|
|
188
|
+
<dimen name="line_height">20dp</dimen>
|
|
189
|
+
</resources>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**HarmonyOS format:**
|
|
193
|
+
```json
|
|
194
|
+
{
|
|
195
|
+
"float": [
|
|
196
|
+
{
|
|
197
|
+
"name": "text_size",
|
|
198
|
+
"value": "16fp"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"name": "margin_large",
|
|
202
|
+
"value": "24vp"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"name": "border_width",
|
|
206
|
+
"value": "1px"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"name": "line_height",
|
|
210
|
+
"value": "20vp"
|
|
211
|
+
}
|
|
212
|
+
]
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Unit mapping:**
|
|
217
|
+
| Android Unit | HarmonyOS Unit | Notes |
|
|
218
|
+
|---|---|---|
|
|
219
|
+
| `dp` | `vp` | Density-independent pixels → virtual pixels |
|
|
220
|
+
| `dip` | `vp` | Same as dp |
|
|
221
|
+
| `sp` | `fp` | Scale-independent pixels → font pixels |
|
|
222
|
+
| `px` | `px` | Physical pixels (keep as-is) |
|
|
223
|
+
| `pt` | `vp` | Points → approximate with vp (multiply by 1.33) |
|
|
224
|
+
| `in` | `vp` | Inches → convert to vp (multiply by 160) |
|
|
225
|
+
| `mm` | `vp` | Millimeters → convert to vp (multiply by 6.3) |
|
|
226
|
+
| (no unit) | `vp` | Plain number → append `vp` |
|
|
227
|
+
|
|
228
|
+
### integers.xml → integer.json
|
|
229
|
+
|
|
230
|
+
**Android format:**
|
|
231
|
+
```xml
|
|
232
|
+
<resources>
|
|
233
|
+
<integer name="max_items">10</integer>
|
|
234
|
+
<integer name="animation_duration">300</integer>
|
|
235
|
+
</resources>
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**HarmonyOS format:**
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"integer": [
|
|
242
|
+
{
|
|
243
|
+
"name": "max_items",
|
|
244
|
+
"value": 10
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"name": "animation_duration",
|
|
248
|
+
"value": 300
|
|
249
|
+
}
|
|
250
|
+
]
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Rules:**
|
|
255
|
+
- **CRITICAL**: Integer values MUST be stored as JSON number type, NOT as JSON strings. `"value": 10` is correct; `"value": "10"` is WRONG and will cause HarmonyOS compilation errors.
|
|
256
|
+
- Parse the XML text content as an integer using `parseInt()` or equivalent. Remove any whitespace before parsing.
|
|
257
|
+
- If the value is a resource reference (`@integer/other`), resolve the reference chain first, then store the final resolved value as a JSON number.
|
|
258
|
+
- If the value contains a hex prefix (`0x`), parse as hexadecimal and store the decimal integer result.
|
|
259
|
+
- If a value cannot be parsed as an integer after resolution, log a warning and use `0` as a fallback.
|
|
260
|
+
- Integer-array values (`<integer-array>`) follow the same rule — each `<item>` value must be a JSON number.
|
|
261
|
+
|
|
262
|
+
### bools.xml → boolean.json
|
|
263
|
+
|
|
264
|
+
**Android format:**
|
|
265
|
+
```xml
|
|
266
|
+
<resources>
|
|
267
|
+
<bool name="is_tablet">false</bool>
|
|
268
|
+
<bool name="show_ads">true</bool>
|
|
269
|
+
</resources>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**HarmonyOS format:**
|
|
273
|
+
```json
|
|
274
|
+
{
|
|
275
|
+
"boolean": [
|
|
276
|
+
{
|
|
277
|
+
"name": "is_tablet",
|
|
278
|
+
"value": false
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"name": "show_ads",
|
|
282
|
+
"value": true
|
|
283
|
+
}
|
|
284
|
+
]
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### arrays.xml → strarray.json / intarray.json
|
|
289
|
+
|
|
290
|
+
**Android string-array:**
|
|
291
|
+
```xml
|
|
292
|
+
<resources>
|
|
293
|
+
<string-array name="colors">
|
|
294
|
+
<item>Red</item>
|
|
295
|
+
<item>Green</item>
|
|
296
|
+
<item>Blue</item>
|
|
297
|
+
</string-array>
|
|
298
|
+
</resources>
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
**HarmonyOS strarray.json:**
|
|
302
|
+
```json
|
|
303
|
+
{
|
|
304
|
+
"strarray": [
|
|
305
|
+
{
|
|
306
|
+
"name": "colors",
|
|
307
|
+
"value": [
|
|
308
|
+
{
|
|
309
|
+
"value": "Red"
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
"value": "Green"
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
"value": "Blue"
|
|
316
|
+
}
|
|
317
|
+
]
|
|
318
|
+
}
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**Android integer-array:**
|
|
324
|
+
```xml
|
|
325
|
+
<resources>
|
|
326
|
+
<integer-array name="scores">
|
|
327
|
+
<item>100</item>
|
|
328
|
+
<item>200</item>
|
|
329
|
+
<item>300</item>
|
|
330
|
+
</integer-array>
|
|
331
|
+
</resources>
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**HarmonyOS intarray.json:**
|
|
335
|
+
```json
|
|
336
|
+
{
|
|
337
|
+
"intarray": [
|
|
338
|
+
{
|
|
339
|
+
"name": "scores",
|
|
340
|
+
"value": [
|
|
341
|
+
{
|
|
342
|
+
"value": 100
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
"value": 200
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
"value": 300
|
|
349
|
+
}
|
|
350
|
+
]
|
|
351
|
+
}
|
|
352
|
+
]
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### plurals.xml → plural.json
|
|
357
|
+
|
|
358
|
+
**Android format:**
|
|
359
|
+
```xml
|
|
360
|
+
<resources>
|
|
361
|
+
<plurals name="items_count">
|
|
362
|
+
<item quantity="one">%d item</item>
|
|
363
|
+
<item quantity="other">%d items</item>
|
|
364
|
+
</plurals>
|
|
365
|
+
</resources>
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**HarmonyOS format:**
|
|
369
|
+
```json
|
|
370
|
+
{
|
|
371
|
+
"plural": [
|
|
372
|
+
{
|
|
373
|
+
"name": "items_count",
|
|
374
|
+
"value": [
|
|
375
|
+
{
|
|
376
|
+
"quantity": "one",
|
|
377
|
+
"value": "%d item"
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"quantity": "other",
|
|
381
|
+
"value": "%d items"
|
|
382
|
+
}
|
|
383
|
+
]
|
|
384
|
+
}
|
|
385
|
+
]
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
**Supported quantities (same for both):** `zero`, `one`, `two`, `few`, `many`, `other`
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## Media Resource Conversion
|
|
394
|
+
|
|
395
|
+
### Drawable images → media
|
|
396
|
+
|
|
397
|
+
Copy image files directly from Android `drawable/` to HarmonyOS `base/media/`:
|
|
398
|
+
- Supported formats in HarmonyOS: PNG, JPG, GIF, SVG, WEBP, BMP
|
|
399
|
+
- All these are also common Android formats, so direct copy works
|
|
400
|
+
- **Do NOT copy XML drawables** (shapes, selectors, vector drawables, layer-lists, ripple effects) — these have no direct HarmonyOS equivalent
|
|
401
|
+
|
|
402
|
+
### Identifying XML vs image drawables
|
|
403
|
+
|
|
404
|
+
In `drawable/` directories, files can be either images or XML:
|
|
405
|
+
- `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.bmp`, `.svg` → image files, copy to `media/`
|
|
406
|
+
- `.xml` → XML drawable, **convert to SVG** (see `references/xml-drawable-to-svg-rules.md` for detailed rules). HarmonyOS supports SVG natively in `media/`. Output as `<original_name>.svg` in the target `media/` directory.
|
|
407
|
+
- `.9.png` → nine-patch image: **rename** `.9.png` to `_9.png` before copying to `media/`. HarmonyOS does not allow `.` characters in resource filenames except for the final extension separator (e.g., `abc_btn.9.png` is an invalid HarmonyOS resource name). Replace the `.9.png` suffix with `_9.png` (e.g., `abc_btn_default.9.png` → `abc_btn_default_9.png`). This renaming must also be applied in all density-qualified directories (`drawable-hdpi/`, `drawable-xhdpi/`, etc.). Log in the conversion report that nine-patch stretching behavior is lost and the developer may need to implement equivalent stretchable behavior in ArkUI code. Also update any references to nine-patch files throughout the converted output to use the new `_9` naming.
|
|
408
|
+
|
|
409
|
+
### XML Drawable → SVG Conversion (Summary)
|
|
410
|
+
|
|
411
|
+
Android XML drawables should be converted to SVG format for HarmonyOS. The main convertible types are:
|
|
412
|
+
|
|
413
|
+
1. **VectorDrawable** (`<vector>`) — Most straightforward. Android's `pathData` uses the same syntax as SVG `d` attribute. Convert `<path>`, `<group>`, `<clip-path>` elements to SVG equivalents.
|
|
414
|
+
|
|
415
|
+
2. **ShapeDrawable** (`<shape>`) — Convert rectangles, ovals, lines, and rings to SVG `<rect>`, `<ellipse>`, `<line>`, or `<circle>` elements with appropriate fill, stroke, and gradient attributes.
|
|
416
|
+
|
|
417
|
+
3. **LayerListDrawable** (`<layer-list>`) — Each `<item>` becomes a nested SVG element, layered in document order.
|
|
418
|
+
|
|
419
|
+
4. **StateListDrawable** (`<selector>`) — Extract the default (no-state) `<item>` or the last `<item>` as fallback, and convert it to SVG. Log the state-dependent items in the conversion report as requiring manual handling.
|
|
420
|
+
|
|
421
|
+
5. **Unconvertible types** — `<ripple>`, `<animated-vector>`, `<animated-selector>`, `<transition>` remain logged as unmappable because they involve runtime behavior that SVG cannot represent.
|
|
422
|
+
|
|
423
|
+
For the complete, detailed conversion rules with examples, read `references/xml-drawable-to-svg-rules.md`.
|
|
424
|
+
|
|
425
|
+
### Mipmap → media
|
|
426
|
+
|
|
427
|
+
Launcher icons from `mipmap/` directories go to `base/media/` (or qualified `media/`):
|
|
428
|
+
- Typically named `ic_launcher.png`, `ic_launcher_round.png`, `ic_launcher_foreground.png`, `ic_launcher_background.png`
|
|
429
|
+
- PNG/WEBP launcher icons → direct copy to target `media/` directory
|
|
430
|
+
- **Adaptive icon XML files** (`<adaptive-icon>` root element, commonly found in `mipmap-anydpi-v26/`) → convert to HarmonyOS layered-image JSON. Parse the XML, extract the `background` and `foreground` layer references, and convert them using the rules below. Output as `<original_name>_layered_image.json` in the target `media/` directory. Only `background` and `foreground` are valid keys under the `"layered-image"` object — skip `monochrome` or any other elements.
|
|
431
|
+
|
|
432
|
+
**Reference conversion rules for layered-image values:**
|
|
433
|
+
- `@drawable/xxx` → `$media:xxx`
|
|
434
|
+
- `@mipmap/xxx` → `$media:xxx`
|
|
435
|
+
- `@color/xxx` → **must NOT use `$color:xxx`** — `layered-image` only accepts `$media:` references. See color-background handling below.
|
|
436
|
+
|
|
437
|
+
**Color background handling (critical):**
|
|
438
|
+
|
|
439
|
+
HarmonyOS `layered-image` does not support `$color:xxx` — only `$media:xxx` is valid for both `background` and `foreground`. When an Android `<background>` (or `<foreground>`) points to a color resource (`@color/xxx`):
|
|
440
|
+
|
|
441
|
+
1. Resolve the actual hex color value by looking it up in the converted `color.json` or the Android `colors.xml`. If the color itself references another color, follow the chain to get the final hex value.
|
|
442
|
+
2. Generate a solid-color PNG image filled entirely with that hex value. Any reasonable dimensions work (e.g., 1×1 px or 108×108 px).
|
|
443
|
+
3. Save the PNG as `<color_name>_bg.png` in `base/media/` (e.g., `md_orange_700_bg.png`).
|
|
444
|
+
4. Use `$media:<color_name>_bg` in the layered-image JSON.
|
|
445
|
+
|
|
446
|
+
**Adaptive icon JSON format example:**
|
|
447
|
+
|
|
448
|
+
For `ic_launcher.xml`:
|
|
449
|
+
```xml
|
|
450
|
+
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
451
|
+
<background android:drawable="@color/md_orange_700" />
|
|
452
|
+
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
|
453
|
+
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
|
454
|
+
</adaptive-icon>
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Suppose `@color/md_orange_700` resolves to `#F57C00`. Generate `base/media/md_orange_700_bg.png` (solid `#F57C00`). Converts to `ic_launcher_layered_image.json`:
|
|
458
|
+
```json
|
|
459
|
+
{
|
|
460
|
+
"layered-image": {
|
|
461
|
+
"background": "$media:md_orange_700_bg",
|
|
462
|
+
"foreground": "$media:ic_launcher_foreground"
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
Note: The `monochrome` element has no HarmonyOS `layered-image` equivalent, so omit it from the JSON output. But do not ignore it entirely — the drawable it references (e.g., `@drawable/ic_launcher_monochrome`) is a real resource that should be converted as a normal drawable and included in dependency analysis. If it's missing from the source `res/` directory (i.e., it comes from a library), record it as an unsatisfied dependency and attempt to recover it via APK decompilation in Step 5, just like any other missing resource.
|
|
468
|
+
- **VectorDrawable XML files** (if found in mipmap directories with `<vector>` root element) → convert to SVG, same as drawable vectors
|
|
469
|
+
|
|
470
|
+
**Common pattern**: `mipmap-anydpi-v26/` is extremely common in Android projects. The qualifier `anydpi-v26` should be parsed as `anydpi` (→ `base`) + `v26` (→ strip). The files inside are typically `<adaptive-icon>` XMLs — process them by reading the XML root element to classify the content type, not by rejecting based on the directory qualifier.
|
|
471
|
+
|
|
472
|
+
### Raw files → rawfile
|
|
473
|
+
|
|
474
|
+
Copy all files from Android `raw/` to HarmonyOS `rawfile/`:
|
|
475
|
+
- Preserve original filenames
|
|
476
|
+
- These are accessed by path in both systems
|
|
477
|
+
|
|
478
|
+
### Font files → rawfile/fonts
|
|
479
|
+
|
|
480
|
+
Copy font files from Android `font/` to HarmonyOS `rawfile/fonts/`:
|
|
481
|
+
- `.ttf`, `.otf`, `.ttc` files → direct copy
|
|
482
|
+
- Font XML files (font family definitions) → log as unmappable
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## Qualifier Mapping
|
|
487
|
+
|
|
488
|
+
### Density Qualifiers
|
|
489
|
+
|
|
490
|
+
The naming conventions differ between Android and HarmonyOS because HarmonyOS uses different DPI range labels:
|
|
491
|
+
|
|
492
|
+
| Android Qualifier | Approx DPI | HarmonyOS Qualifier | HarmonyOS DPI Range |
|
|
493
|
+
|---|---|---|---|
|
|
494
|
+
| `ldpi` | 120 | `sdpi` | (0, 120] |
|
|
495
|
+
| `mdpi` | 160 | `mdpi` | (120, 160] |
|
|
496
|
+
| `tvdpi` | 213 | `ldpi` | (160, 240] |
|
|
497
|
+
| `hdpi` | 240 | `ldpi` | (160, 240] |
|
|
498
|
+
| `xhdpi` | 320 | `xldpi` | (240, 320] |
|
|
499
|
+
| `xxhdpi` | 480 | `xxldpi` | (320, 480] |
|
|
500
|
+
| `xxxhdpi` | 640 | `xxxldpi` | (480, 640] |
|
|
501
|
+
| `nodpi` | N/A | `base` | No density qualifier; use base |
|
|
502
|
+
| `anydpi` | N/A | `base` | No density qualifier; use base |
|
|
503
|
+
|
|
504
|
+
### Language/Region Qualifiers
|
|
505
|
+
|
|
506
|
+
Android format: `<type>-<language>` or `<type>-<language>-r<REGION>`
|
|
507
|
+
HarmonyOS format: `<language>` or `<language>_<REGION>`
|
|
508
|
+
|
|
509
|
+
**Examples:**
|
|
510
|
+
| Android | HarmonyOS |
|
|
511
|
+
|---|---|
|
|
512
|
+
| `values-ar` | `ar/element/` |
|
|
513
|
+
| `values-zh` | `zh/element/` |
|
|
514
|
+
| `values-zh-rCN` | `zh_CN/element/` |
|
|
515
|
+
| `values-zh-rTW` | `zh_TW/element/` |
|
|
516
|
+
| `values-en` | `en/element/` |
|
|
517
|
+
| `values-en-rUS` | `en_US/element/` |
|
|
518
|
+
| `values-en-rGB` | `en_GB/element/` |
|
|
519
|
+
| `values-fr-rFR` | `fr_FR/element/` |
|
|
520
|
+
| `values-ja` | `ja/element/` |
|
|
521
|
+
| `values-ko` | `ko/element/` |
|
|
522
|
+
| `drawable-zh-rCN-hdpi` | `zh_CN-ldpi/media/` |
|
|
523
|
+
|
|
524
|
+
**Parsing Android language qualifiers:**
|
|
525
|
+
- Language code: 2 or 3 lowercase letters (ISO 639)
|
|
526
|
+
- Region code: preceded by `r`, 2 uppercase letters (ISO 3166-1) — strip the `r` prefix
|
|
527
|
+
- Script code (BCP 47): preceded by `b+`, e.g., `b+sr+Latn` → `sr_Latn`
|
|
528
|
+
|
|
529
|
+
### Orientation Qualifiers
|
|
530
|
+
|
|
531
|
+
| Android | HarmonyOS |
|
|
532
|
+
|---|---|
|
|
533
|
+
| `land` | `horizontal` |
|
|
534
|
+
| `port` | `vertical` |
|
|
535
|
+
|
|
536
|
+
### Night Mode Qualifiers
|
|
537
|
+
|
|
538
|
+
| Android | HarmonyOS |
|
|
539
|
+
|---|---|
|
|
540
|
+
| `night` | `dark` |
|
|
541
|
+
| `notnight` | `light` |
|
|
542
|
+
|
|
543
|
+
### Combining Multiple Qualifiers
|
|
544
|
+
|
|
545
|
+
Android directory names can contain multiple qualifiers separated by hyphens, e.g., `drawable-zh-rCN-night-hdpi` or `mipmap-anydpi-v26`.
|
|
546
|
+
|
|
547
|
+
**Parsing algorithm for any Android resource directory name:**
|
|
548
|
+
|
|
549
|
+
1. Split the directory name by `-` to get segments
|
|
550
|
+
2. The first segment is the resource type (`drawable`, `mipmap`, `values`, etc.)
|
|
551
|
+
3. The remaining segments are qualifiers. Parse them left-to-right, recognizing:
|
|
552
|
+
- Language codes: 2-3 lowercase letters (e.g., `zh`, `ar`, `en`)
|
|
553
|
+
- Region codes: `r` + 2 uppercase letters (e.g., `rCN`, `rUS`) — always follows a language
|
|
554
|
+
- Density: `ldpi`, `mdpi`, `hdpi`, `xhdpi`, `xxhdpi`, `xxxhdpi`, `nodpi`, `anydpi`, `tvdpi`
|
|
555
|
+
- Orientation: `land`, `port`
|
|
556
|
+
- Night mode: `night`, `notnight`
|
|
557
|
+
- API level: `v` followed by digits (e.g., `v26`, `v21`) — **strip, do not reject**
|
|
558
|
+
- Screen size qualifiers: `sw<N>dp`, `w<N>dp`, `h<N>dp`, `small`, `normal`, `large`, `xlarge` — **skip entire directory, mark as unmapped**
|
|
559
|
+
- Other unsupported qualifiers — **strip, do not reject**
|
|
560
|
+
4. Map each recognized qualifier to its HarmonyOS equivalent
|
|
561
|
+
5. Strip only API-level, layout direction, screen shape, HDR, and aspect qualifiers (see "Unsupported Android Qualifiers" below)
|
|
562
|
+
6. If any screen-size qualifiers remain (`sw<N>dp`, `w<N>dp`, `h<N>dp`, `small`/`normal`/`large`/`xlarge`), skip the entire directory — mark all resources as "unmapped" with reason "Unsupported qualifier"
|
|
563
|
+
7. If no mappable or preserved qualifiers remain after stripping, use `base/`
|
|
564
|
+
8. Reassemble remaining HarmonyOS qualifiers in correct order: MCC_MNC-language_script_country/region-orientation-device-colormode-density (preserved qualifiers go at the end)
|
|
565
|
+
|
|
566
|
+
**Examples:**
|
|
567
|
+
| Android Directory | Type | Qualifiers | HarmonyOS Dir |
|
|
568
|
+
|---|---|---|---|
|
|
569
|
+
| `drawable-hdpi` | drawable | hdpi→ldpi | `ldpi/media/` |
|
|
570
|
+
| `mipmap-anydpi-v26` | mipmap | anydpi→base, v26→stripped | `base/media/` |
|
|
571
|
+
| `drawable-zh-rCN-night-hdpi` | drawable | zh-rCN→zh_CN, night→dark, hdpi→ldpi | `zh_CN-dark-ldpi/media/` |
|
|
572
|
+
| `values-ko-rKR` | values | ko-rKR→ko_KR | `ko_KR/element/` |
|
|
573
|
+
| `drawable-night-v21` | drawable | night→dark, v21→stripped | `dark/media/` |
|
|
574
|
+
|
|
575
|
+
### Unsupported Android Qualifiers
|
|
576
|
+
|
|
577
|
+
These Android qualifiers have no HarmonyOS equivalent. When encountered, **strip them** from the qualifier list (do not reject the directory). If stripping leaves no remaining qualifiers, use `base/`. If other valid qualifiers remain, use those.
|
|
578
|
+
|
|
579
|
+
Unsupported qualifiers to strip:
|
|
580
|
+
- API level `v<N>` (e.g., `v26`, `v21`, `v31`)
|
|
581
|
+
- Layout direction (`ldrtl`, `ldltr`)
|
|
582
|
+
- `round`, `notround` (screen shape)
|
|
583
|
+
- `highdr`, `lowdr` (HDR)
|
|
584
|
+
- `long`, `notlong` (screen aspect)
|
|
585
|
+
|
|
586
|
+
**Qualifiers without a HarmonyOS equivalent** (skip entirely, do NOT convert):
|
|
587
|
+
- `sw<N>dp` (smallest width, e.g., `sw600dp`)
|
|
588
|
+
- `w<N>dp` (available width, e.g., `w480dp`, `w600dp`)
|
|
589
|
+
- `h<N>dp` (available height)
|
|
590
|
+
- `small`, `normal`, `large`, `xlarge` (screen size)
|
|
591
|
+
|
|
592
|
+
These qualifiers have no HarmonyOS mapping. When a directory's only remaining qualifiers (after stripping API level etc.) are from this list, **skip all resources in that directory entirely**. Mark them as "unmapped" in the conversion report with reason "Unsupported qualifier: no HarmonyOS equivalent". Do NOT place them in `base/` or preserve the qualifier as-is — skipping avoids incorrect conversions.
|
|
593
|
+
|
|
594
|
+
**Important: multi-qualifier directory handling.** Android directory names often combine multiple qualifiers with hyphens. When parsing, extract ALL qualifiers, map each one independently, strip any unsupported ones, and then assemble the HarmonyOS qualifier from whatever remains.
|
|
595
|
+
|
|
596
|
+
**Examples of stripping unsupported qualifiers:**
|
|
597
|
+
|
|
598
|
+
| Android Directory | Qualifiers Parsed | After Mapping | HarmonyOS Target |
|
|
599
|
+
|---|---|---|---|
|
|
600
|
+
| `mipmap-anydpi-v26` | `anydpi` + `v26` | `anydpi` → `base`, `v26` → stripped | `base/media/` |
|
|
601
|
+
| `drawable-night-v21` | `night` + `v21` | `night` → `dark`, `v21` → stripped | `dark/media/` |
|
|
602
|
+
| `values-sw600dp` | `sw600dp` | **skip — unmapped** | N/A (skipped) |
|
|
603
|
+
| `values-w480dp` | `w480dp` | **skip — unmapped** | N/A (skipped) |
|
|
604
|
+
| `drawable-hdpi-v4` | `hdpi` + `v4` | `hdpi` → `ldpi`, `v4` → stripped | `ldpi/media/` |
|
|
605
|
+
|
|
606
|
+
The key principle: API-level qualifiers (`v<N>`) and a few others (layout direction, screen shape, HDR, aspect) are **silently stripped**. Screen-size qualifiers (`sw<N>dp`, `w<N>dp`, `h<N>dp`, `small`/`normal`/`large`/`xlarge`) cause the **entire directory to be skipped** — resources are marked as "unmapped" in the report because HarmonyOS has no equivalent qualifier. This avoids incorrect conversions and keeps the output clean.
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## Special Cases and Edge Cases
|
|
611
|
+
|
|
612
|
+
### Multiple values files contributing to the same JSON
|
|
613
|
+
|
|
614
|
+
Android projects often have multiple XML files under `values/` that all contain `<string>` or `<color>` entries. For example:
|
|
615
|
+
- `values/strings.xml` — main strings
|
|
616
|
+
- `values/strings_feature.xml` — feature-specific strings
|
|
617
|
+
- `values/google_strings.xml` — library strings
|
|
618
|
+
|
|
619
|
+
All `<string>` entries from any file go into a single `string.json`. Similarly for colors, dimens, etc. Collect entries across all files before writing.
|
|
620
|
+
|
|
621
|
+
### Resource name conflicts
|
|
622
|
+
|
|
623
|
+
If two files define the same resource name, the last one wins (matching Android's behavior where later entries override earlier ones). Log these conflicts in the report.
|
|
624
|
+
|
|
625
|
+
### Android resource references
|
|
626
|
+
|
|
627
|
+
Android values may reference other resources: `@string/other_string`, `@color/primary`, `@dimen/margin`. These references don't have a direct equivalent in HarmonyOS element JSON. Convert them as:
|
|
628
|
+
- `@string/name` → `$string:name`
|
|
629
|
+
- `@color/name` → `$color:name`
|
|
630
|
+
- `@dimen/name` → `$float:name`
|
|
631
|
+
- `@integer/name` → `$integer:name`
|
|
632
|
+
- `@bool/name` → `$boolean:name`
|
|
633
|
+
- `?attr/name` → log as unmappable (theme attribute reference)
|
|
634
|
+
|
|
635
|
+
### Android system resource references
|
|
636
|
+
|
|
637
|
+
References like `@android:color/black` or `@android:string/ok` are Android system resources provided by the framework. These do NOT exist in HarmonyOS and MUST be resolved to concrete values during conversion — they cannot be left as `@android:` references in the output.
|
|
638
|
+
|
|
639
|
+
**Resolution rules:**
|
|
640
|
+
- `@android:color/*` — resolve using the built-in Android system color lookup table (see SKILL.md Step 5.2 for the complete table). Common examples: `@android:color/white` → `#ffffffff`, `@android:color/black` → `#ff000000`, `@android:color/transparent` → `#00000000`.
|
|
641
|
+
- `@android:dimen/*` — resolve using the built-in system dimension lookup table (see SKILL.md Step 5.2).
|
|
642
|
+
- `@android:string/*` — resolve to the known English string value. Common: `@android:string/ok` → `"OK"`, `@android:string/cancel` → `"Cancel"`.
|
|
643
|
+
- `@android:integer/*` — resolve to the known integer value.
|
|
644
|
+
- For any `@android:type/name` not found in the lookup tables, log a warning in the report and substitute a type-appropriate default (colors → `#ff000000`, dimens → `0vp`, integers → `0`, strings → `""`).
|
|
645
|
+
- When converting from a decompiled APK, the framework resource values can also be found in the decompiled output — use those as a secondary source.
|
|
646
|
+
|
|
647
|
+
**NEVER leave `@android:` references in the final HarmonyOS output.** They will cause compilation errors since HarmonyOS has no concept of Android system resources.
|
|
648
|
+
|
|
649
|
+
### Empty or comment-only XML files
|
|
650
|
+
|
|
651
|
+
Skip these silently — don't create empty JSON files.
|
|
652
|
+
|
|
653
|
+
### Large resource sets
|
|
654
|
+
|
|
655
|
+
When an Android project has hundreds of resources, process them systematically:
|
|
656
|
+
1. First scan and inventory all resources
|
|
657
|
+
2. Group by type and qualifier
|
|
658
|
+
3. Convert each group
|
|
659
|
+
4. Verify completeness
|
|
660
|
+
|
|
661
|
+
### XML encoding and BOM
|
|
662
|
+
|
|
663
|
+
Some Android XML files may have BOM (Byte Order Mark) or non-UTF-8 encoding declarations. Handle these gracefully — read with the declared encoding, output UTF-8 JSON.
|