deveco_hmigbot 0.21.5
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/LICENSE +26 -0
- package/README.md +50 -0
- package/agents/hmigbot-worker.md +61 -0
- package/agents/hmigbot.md +22 -0
- package/agents/workflow-subagent.md +55 -0
- package/commands/hmigbot.md +17 -0
- package/dist/index.js +1 -0
- package/manifest.json +19 -0
- package/package.json +29 -0
- package/skills/migrate-core/FILES.md +26 -0
- package/skills/migrate-core/SKILL.md +484 -0
- package/skills/migrate-core/references/README.md +64 -0
- package/skills/migrate-core/references/flow/arkts-vector-gate.md +55 -0
- package/skills/migrate-core/references/flow/build-error-patterns.md +52 -0
- package/skills/migrate-core/references/flow/conventions-template.md +244 -0
- package/skills/migrate-core/references/flow/navigation-migration.md +42 -0
- package/skills/migrate-core/references/flow/platform-api-guards.md +59 -0
- package/skills/migrate-core/references/flow/platform-model-gaps.md +43 -0
- package/skills/migrate-core/references/flow/resource-conversion.md +46 -0
- package/skills/migrate-core/references/flow/ui-layout-semantics.md +124 -0
- package/skills/migrate-core/references/flow/unit-breakdown.md +42 -0
- package/skills/migrate-core/references/host-capabilities.md +24 -0
- package/skills/migrate-core/references/topics/app-identity.md +214 -0
- package/skills/migrate-core/references/topics/env-doctor.md +245 -0
- package/skills/migrate-core/references/topics/i18n/README.md +458 -0
- package/skills/migrate-core/references/topics/i18n/references/code-examples.md +304 -0
- package/skills/migrate-core/references/topics/i18n/references/common-pitfalls.md +354 -0
- package/skills/migrate-core/references/topics/i18n/references/dynamic-language-switch.md +464 -0
- package/skills/migrate-core/references/topics/i18n/references/language-codes.md +104 -0
- package/skills/migrate-core/references/topics/icon-sizing.md +98 -0
- package/skills/migrate-core/references/topics/library-migration/README.md +234 -0
- package/skills/migrate-core/references/topics/library-migration/closed-source-sdk.md +128 -0
- package/skills/migrate-core/references/topics/library-migration/download-api-decision.md +84 -0
- package/skills/migrate-core/references/topics/library-migration/library-mapping-table.md +100 -0
- package/skills/migrate-core/references/topics/library-migration/napi-compile-guide.md +84 -0
- package/skills/migrate-core/references/topics/library-migration/ohpm-search-guide.md +73 -0
- package/skills/migrate-core/references/topics/library-migration/stdlib-mapping-table.md +34 -0
- package/skills/migrate-core/references/topics/resources/aar-decompile.md +25 -0
- package/skills/migrate-core/references/topics/resources/conversion-rules.md +625 -0
- package/skills/migrate-core/references/topics/resources/dependency-analysis-rules.md +328 -0
- package/skills/migrate-core/references/topics/resources/material-design-icons.md +173 -0
- package/skills/migrate-core/references/topics/resources/svg-fix-patterns.md +175 -0
- package/skills/migrate-core/references/topics/resources/xml-drawable-to-svg-rules.md +513 -0
- package/skills/migrate-core/references/topics/system-capabilities/README.md +331 -0
- package/skills/migrate-core/references/topics/system-capabilities/avplayer-guide.md +161 -0
- package/skills/migrate-core/references/topics/system-capabilities/background-tasks.md +403 -0
- package/skills/migrate-core/references/topics/system-capabilities/browser-intent.md +121 -0
- package/skills/migrate-core/references/topics/system-capabilities/camera-picker.md +118 -0
- package/skills/migrate-core/references/topics/system-capabilities/document-picker.md +246 -0
- package/skills/migrate-core/references/topics/system-capabilities/file-utils.md +131 -0
- package/skills/migrate-core/references/topics/system-capabilities/permission-helper.md +112 -0
- package/skills/migrate-core/references/topics/system-capabilities/photo-access-helper.md +208 -0
- package/skills/migrate-core/references/topics/system-capabilities/print-management.md +213 -0
- package/skills/migrate-core/references/topics/system-capabilities/share-panel.md +177 -0
- package/skills/migrate-core/references/topics/system-capabilities/system-settings.md +322 -0
- package/skills/migrate-core/references/topics/system-capabilities/telephony-dial.md +49 -0
- package/skills/migrate-core/references/topics/system-capabilities/video-playback.md +42 -0
- package/skills/migrate-core/references/topics/system-capabilities/webview-patterns.md +38 -0
- package/skills/migrate-core/references/topics/ui-alignment/README.md +344 -0
- package/skills/migrate-core/references/topics/ui-alignment/references/dark-mode.md +47 -0
- package/skills/migrate-core/references/topics/ui-alignment/references/layout-mapping.md +301 -0
- package/skills/migrate-core/references/topics/ui-alignment/references/visual-patterns.md +411 -0
- package/skills/migrate-core/scripts/closure/check-anchors.mjs +186 -0
- package/skills/migrate-core/scripts/closure/check-api-guards.mjs +175 -0
- package/skills/migrate-core/scripts/closure/check-consumers.mjs +301 -0
- package/skills/migrate-core/scripts/closure/check-permissions.mjs +165 -0
- package/skills/migrate-core/scripts/closure/check-resources.mjs +130 -0
- package/skills/migrate-core/scripts/closure/check-routes.mjs +527 -0
- package/skills/migrate-core/scripts/closure/check-safearea.mjs +122 -0
- package/skills/migrate-core/scripts/closure/check-stubs.mjs +69 -0
- package/skills/migrate-core/scripts/closure/closure-suite.mjs +256 -0
- package/skills/migrate-core/scripts/closure/idioms.json +105 -0
- package/skills/migrate-core/scripts/convert/convert-resources.mjs +437 -0
- package/skills/migrate-core/scripts/feasibility/feasibility.mjs +235 -0
- package/skills/migrate-core/scripts/feasibility/tables/cross-platform.json +11 -0
- package/skills/migrate-core/scripts/feasibility/tables/deprecated-api.json +10 -0
- package/skills/migrate-core/scripts/feasibility/tables/imported-arkts-core.json +425 -0
- package/skills/migrate-core/scripts/feasibility/tables/lib-equivalence.json +206 -0
- package/skills/migrate-core/scripts/feasibility/tables/system-capabilities.json +22 -0
- package/skills/migrate-core/scripts/front.mjs +107 -0
- package/skills/migrate-core/scripts/interface/ark-extract.mjs +172 -0
- package/skills/migrate-core/scripts/interface/interface.mjs +152 -0
- package/skills/migrate-core/scripts/ledger/ledger.mjs +383 -0
- package/skills/migrate-core/scripts/ledger/parse-cards.mjs +98 -0
- package/skills/migrate-core/scripts/lib/literals.mjs +37 -0
- package/skills/migrate-core/scripts/lib/scan.mjs +315 -0
- package/skills/migrate-core/scripts/smoke/align-sdk.mjs +118 -0
- package/skills/migrate-core/scripts/smoke/ensure-sign.mjs +53 -0
- package/skills/migrate-core/scripts/smoke/smoke.mjs +238 -0
- package/skills/migrate-core/scripts/smoke/verdict.mjs +31 -0
- package/skills/migrate-core/scripts/smoke/walk.mjs +480 -0
- package/skills/migrate-core/scripts/transpile/mapping.json +76 -0
- package/skills/migrate-core/scripts/transpile/transpile-layout.mjs +404 -0
- package/skills/migrate-core/scripts/vectors/run-arkts-vectors.mjs +107 -0
- package/skills/migrate-core/scripts/vectors/setup-arkts-test.mjs +90 -0
- package/skills/migrate-core/scripts/wire/extractors.mjs +258 -0
- package/skills/migrate-core/scripts/wire/wire-routes.mjs +507 -0
- package/skills/migrate-core/templates/acceptance.js +365 -0
- package/skills/migrate-core/templates/explore.js +86 -0
- package/skills/migrate-core/templates/implement.js +211 -0
- package/skills/migrate-core/templates/mig_slices.js +491 -0
|
@@ -0,0 +1,625 @@
|
|
|
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.
|
|
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
|
+
---
|
|
68
|
+
|
|
69
|
+
## Values XML to Element JSON Conversion
|
|
70
|
+
|
|
71
|
+
### strings.xml → string.json
|
|
72
|
+
|
|
73
|
+
**Android format:**
|
|
74
|
+
```xml
|
|
75
|
+
<resources>
|
|
76
|
+
<string name="app_name">My App</string>
|
|
77
|
+
<string name="greeting">Hello, %1$s! You have %2$d messages.</string>
|
|
78
|
+
<string name="with_apostrophe">It\'s a test</string>
|
|
79
|
+
<string name="with_html"><![CDATA[<b>Bold</b> text]]></string>
|
|
80
|
+
</resources>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**HarmonyOS format:**
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"string": [
|
|
87
|
+
{
|
|
88
|
+
"name": "app_name",
|
|
89
|
+
"value": "My App"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "greeting",
|
|
93
|
+
"value": "Hello, %1$s! You have %2$d messages."
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"name": "with_apostrophe",
|
|
97
|
+
"value": "It's a test"
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "with_html",
|
|
101
|
+
"value": "<b>Bold</b> text"
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Rules:**
|
|
108
|
+
- Remove Android escape sequences: `\'` → `'`, `\"` → `"`
|
|
109
|
+
- Decode XML entities: `&` → `&`, `<` → `<`, `>` → `>`, `"` → `"`, `'` → `'`
|
|
110
|
+
- Extract text from CDATA sections
|
|
111
|
+
- Preserve format placeholders (`%1$s`, `%2$d`, etc.) — HarmonyOS uses the same format
|
|
112
|
+
- ⚠️ **DO NOT drop the `$`**: Android positional format is `%1$s` / `%2$d`. A common silent bug is emitting `%1s` / `%2d` (no `$`). HarmonyOS `resourceManager.getStringSync(id, arg)` / `getPluralStringValueSync` only recognize `%s` / `%d` / `%1$s`; `%1s` / `%1d` are **invalid.
|
|
113
|
+
- **Mandatory self-check after writing string.json / plural.json**: `grep -rEn "%[0-9]+[a-z]" <out>/element/*.json` — any hit of `%<digit><letter>` WITHOUT a `$` (e.g. `%1s`, `%2d`) is a malformed placeholder; fix to `%1$s` / `%2$d`.
|
|
114
|
+
- If the string value is wrapped in quotes in Android XML (`"some text"`), remove the outer quotes
|
|
115
|
+
- Skip `<string>` elements with `translatable="false"` attribute? No — still include them, as they may be used at runtime. But note the translatable status.
|
|
116
|
+
|
|
117
|
+
### colors.xml → color.json
|
|
118
|
+
|
|
119
|
+
**Android format:**
|
|
120
|
+
```xml
|
|
121
|
+
<resources>
|
|
122
|
+
<color name="primary">#FF6200EE</color>
|
|
123
|
+
<color name="background">#FFFFFF</color>
|
|
124
|
+
<color name="semi_transparent">#80000000</color>
|
|
125
|
+
<color name="shorthand">#F00</color>
|
|
126
|
+
</resources>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**HarmonyOS format:**
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"color": [
|
|
133
|
+
{
|
|
134
|
+
"name": "primary",
|
|
135
|
+
"value": "#FF6200EE"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
"name": "background",
|
|
139
|
+
"value": "#ffFFFFFF"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"name": "semi_transparent",
|
|
143
|
+
"value": "#80000000"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"name": "shorthand",
|
|
147
|
+
"value": "#ffFF0000"
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Rules:**
|
|
154
|
+
- `#AARRGGBB` (8 digits) → keep as-is (HarmonyOS uses same format: first 2 = opacity)
|
|
155
|
+
- `#RRGGBB` (6 digits) → prepend `ff` → `#ffRRGGBB`
|
|
156
|
+
- `#ARGB` (4 digits) → expand each: `#8F00` → `#88FF0000`
|
|
157
|
+
- `#RGB` (3 digits) → expand each and add `ff`: `#F00` → `#ffFF0000`
|
|
158
|
+
- Color values are case-insensitive in Android; preserve original case or normalize
|
|
159
|
+
|
|
160
|
+
### dimens.xml → float.json
|
|
161
|
+
|
|
162
|
+
**Android format:**
|
|
163
|
+
```xml
|
|
164
|
+
<resources>
|
|
165
|
+
<dimen name="text_size">16sp</dimen>
|
|
166
|
+
<dimen name="margin_large">24dp</dimen>
|
|
167
|
+
<dimen name="border_width">1px</dimen>
|
|
168
|
+
<dimen name="line_height">20dp</dimen>
|
|
169
|
+
</resources>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**HarmonyOS format:**
|
|
173
|
+
```json
|
|
174
|
+
{
|
|
175
|
+
"float": [
|
|
176
|
+
{
|
|
177
|
+
"name": "text_size",
|
|
178
|
+
"value": "16fp"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"name": "margin_large",
|
|
182
|
+
"value": "24vp"
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"name": "border_width",
|
|
186
|
+
"value": "1px"
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
"name": "line_height",
|
|
190
|
+
"value": "20vp"
|
|
191
|
+
}
|
|
192
|
+
]
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Unit mapping:**
|
|
197
|
+
| Android Unit | HarmonyOS Unit | Notes |
|
|
198
|
+
|---|---|---|
|
|
199
|
+
| `dp` | `vp` | Density-independent pixels → virtual pixels |
|
|
200
|
+
| `dip` | `vp` | Same as dp |
|
|
201
|
+
| `sp` | `fp` | Scale-independent pixels → font pixels |
|
|
202
|
+
| `px` | `px` | Physical pixels (keep as-is) |
|
|
203
|
+
| `pt` | `vp` | Points → convert to vp (multiply by 2.22 — 1pt = 1/72 inch = 160/72 dp; same 160dp/inch baseline as `in`/`mm` below) |
|
|
204
|
+
| `in` | `vp` | Inches → convert to vp (multiply by 160) |
|
|
205
|
+
| `mm` | `vp` | Millimeters → convert to vp (multiply by 6.3) |
|
|
206
|
+
| (no unit) | `vp` | Plain number → append `vp` |
|
|
207
|
+
|
|
208
|
+
### integers.xml → integer.json
|
|
209
|
+
|
|
210
|
+
**Android format:**
|
|
211
|
+
```xml
|
|
212
|
+
<resources>
|
|
213
|
+
<integer name="max_items">10</integer>
|
|
214
|
+
<integer name="animation_duration">300</integer>
|
|
215
|
+
</resources>
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**HarmonyOS format:**
|
|
219
|
+
```json
|
|
220
|
+
{
|
|
221
|
+
"integer": [
|
|
222
|
+
{
|
|
223
|
+
"name": "max_items",
|
|
224
|
+
"value": 10
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"name": "animation_duration",
|
|
228
|
+
"value": 300
|
|
229
|
+
}
|
|
230
|
+
]
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### bools.xml → boolean.json
|
|
235
|
+
|
|
236
|
+
**Android format:**
|
|
237
|
+
```xml
|
|
238
|
+
<resources>
|
|
239
|
+
<bool name="is_tablet">false</bool>
|
|
240
|
+
<bool name="show_ads">true</bool>
|
|
241
|
+
</resources>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**HarmonyOS format:**
|
|
245
|
+
```json
|
|
246
|
+
{
|
|
247
|
+
"boolean": [
|
|
248
|
+
{
|
|
249
|
+
"name": "is_tablet",
|
|
250
|
+
"value": false
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
"name": "show_ads",
|
|
254
|
+
"value": true
|
|
255
|
+
}
|
|
256
|
+
]
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### arrays.xml → strarray.json / intarray.json
|
|
261
|
+
|
|
262
|
+
**Android string-array:**
|
|
263
|
+
```xml
|
|
264
|
+
<resources>
|
|
265
|
+
<string-array name="colors">
|
|
266
|
+
<item>Red</item>
|
|
267
|
+
<item>Green</item>
|
|
268
|
+
<item>Blue</item>
|
|
269
|
+
</string-array>
|
|
270
|
+
</resources>
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**HarmonyOS strarray.json:**
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
"strarray": [
|
|
277
|
+
{
|
|
278
|
+
"name": "colors",
|
|
279
|
+
"value": [
|
|
280
|
+
{
|
|
281
|
+
"value": "Red"
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
"value": "Green"
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
"value": "Blue"
|
|
288
|
+
}
|
|
289
|
+
]
|
|
290
|
+
}
|
|
291
|
+
]
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
**Android integer-array:**
|
|
296
|
+
```xml
|
|
297
|
+
<resources>
|
|
298
|
+
<integer-array name="scores">
|
|
299
|
+
<item>100</item>
|
|
300
|
+
<item>200</item>
|
|
301
|
+
<item>300</item>
|
|
302
|
+
</integer-array>
|
|
303
|
+
</resources>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**HarmonyOS intarray.json:**
|
|
307
|
+
```json
|
|
308
|
+
{
|
|
309
|
+
"intarray": [
|
|
310
|
+
{
|
|
311
|
+
"name": "scores",
|
|
312
|
+
"value": [
|
|
313
|
+
{
|
|
314
|
+
"value": 100
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"value": 200
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
"value": 300
|
|
321
|
+
}
|
|
322
|
+
]
|
|
323
|
+
}
|
|
324
|
+
]
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### plurals.xml → plural.json
|
|
329
|
+
|
|
330
|
+
**Android format:**
|
|
331
|
+
```xml
|
|
332
|
+
<resources>
|
|
333
|
+
<plurals name="items_count">
|
|
334
|
+
<item quantity="one">%d item</item>
|
|
335
|
+
<item quantity="other">%d items</item>
|
|
336
|
+
</plurals>
|
|
337
|
+
</resources>
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
**HarmonyOS format:**
|
|
341
|
+
```json
|
|
342
|
+
{
|
|
343
|
+
"plural": [
|
|
344
|
+
{
|
|
345
|
+
"name": "items_count",
|
|
346
|
+
"value": [
|
|
347
|
+
{
|
|
348
|
+
"quantity": "one",
|
|
349
|
+
"value": "%d item"
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"quantity": "other",
|
|
353
|
+
"value": "%d items"
|
|
354
|
+
}
|
|
355
|
+
]
|
|
356
|
+
}
|
|
357
|
+
]
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**Supported quantities (same for both):** `zero`, `one`, `two`, `few`, `many`, `other`
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Media Resource Conversion
|
|
366
|
+
|
|
367
|
+
### Drawable images → media
|
|
368
|
+
|
|
369
|
+
Copy image files directly from Android `drawable/` to HarmonyOS `base/media/`:
|
|
370
|
+
- Supported formats in HarmonyOS: PNG, JPG, GIF, SVG, WEBP, BMP
|
|
371
|
+
- All these are also common Android formats, so direct copy works
|
|
372
|
+
- **Do NOT copy XML drawables** (shapes, selectors, vector drawables, layer-lists, ripple effects) — these have no direct HarmonyOS equivalent
|
|
373
|
+
|
|
374
|
+
### Identifying XML vs image drawables
|
|
375
|
+
|
|
376
|
+
In `drawable/` directories, files can be either images or XML:
|
|
377
|
+
- `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp`, `.bmp`, `.svg` → image files, copy to `media/`
|
|
378
|
+
- `.xml` → XML drawable, **convert to SVG** (see `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.
|
|
379
|
+
- `.9.png` → nine-patch image, copy to `media/` (note: HarmonyOS doesn't natively support nine-patch, but the file can still be used)
|
|
380
|
+
|
|
381
|
+
### XML Drawable → SVG Conversion (Summary)
|
|
382
|
+
|
|
383
|
+
Android XML drawables should be converted to SVG format for HarmonyOS. The main convertible types are:
|
|
384
|
+
|
|
385
|
+
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.
|
|
386
|
+
|
|
387
|
+
2. **ShapeDrawable** (`<shape>`) — Convert rectangles, ovals, lines, and rings to SVG `<rect>`, `<ellipse>`, `<line>`, or `<circle>` elements with appropriate fill, stroke, and gradient attributes.
|
|
388
|
+
|
|
389
|
+
3. **LayerListDrawable** (`<layer-list>`) — Each `<item>` becomes a nested SVG element, layered in document order.
|
|
390
|
+
|
|
391
|
+
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.
|
|
392
|
+
|
|
393
|
+
5. **Unconvertible types** — `<ripple>`, `<animated-vector>`, `<animated-selector>`, `<transition>` remain logged as unmappable because they involve runtime behavior that SVG cannot represent.
|
|
394
|
+
|
|
395
|
+
For the complete, detailed conversion rules with examples, read `xml-drawable-to-svg-rules.md`.
|
|
396
|
+
|
|
397
|
+
### Mipmap → media
|
|
398
|
+
|
|
399
|
+
Launcher icons from `mipmap/` directories go to `base/media/` (or qualified `media/`):
|
|
400
|
+
- Typically named `ic_launcher.png`, `ic_launcher_round.png`, `ic_launcher_foreground.png`, `ic_launcher_background.png`
|
|
401
|
+
- PNG/WEBP launcher icons → direct copy to target `media/` directory
|
|
402
|
+
- **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.
|
|
403
|
+
|
|
404
|
+
**Reference conversion rules for layered-image values:**
|
|
405
|
+
- `@drawable/xxx` → `$media:xxx`
|
|
406
|
+
- `@mipmap/xxx` → `$media:xxx`
|
|
407
|
+
- `@color/xxx` → **must NOT use `$color:xxx`** — `layered-image` only accepts `$media:` references. See color-background handling below.
|
|
408
|
+
|
|
409
|
+
**Color background handling (critical):**
|
|
410
|
+
|
|
411
|
+
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`):
|
|
412
|
+
|
|
413
|
+
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.
|
|
414
|
+
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).
|
|
415
|
+
3. Save the PNG as `<color_name>_bg.png` in `base/media/` (e.g., `md_orange_700_bg.png`).
|
|
416
|
+
4. Use `$media:<color_name>_bg` in the layered-image JSON.
|
|
417
|
+
|
|
418
|
+
**Adaptive icon JSON format example:**
|
|
419
|
+
|
|
420
|
+
For `ic_launcher.xml`:
|
|
421
|
+
```xml
|
|
422
|
+
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
|
423
|
+
<background android:drawable="@color/md_orange_700" />
|
|
424
|
+
<foreground android:drawable="@mipmap/ic_launcher_foreground" />
|
|
425
|
+
<monochrome android:drawable="@drawable/ic_launcher_monochrome" />
|
|
426
|
+
</adaptive-icon>
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
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`:
|
|
430
|
+
```json
|
|
431
|
+
{
|
|
432
|
+
"layered-image": {
|
|
433
|
+
"background": "$media:md_orange_700_bg",
|
|
434
|
+
"foreground": "$media:ic_launcher_foreground"
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
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.
|
|
440
|
+
- **VectorDrawable XML files** (if found in mipmap directories with `<vector>` root element) → convert to SVG, same as drawable vectors
|
|
441
|
+
|
|
442
|
+
**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.
|
|
443
|
+
|
|
444
|
+
### Raw files → rawfile
|
|
445
|
+
|
|
446
|
+
Copy all files from Android `raw/` to HarmonyOS `rawfile/`:
|
|
447
|
+
- Preserve original filenames
|
|
448
|
+
- These are accessed by path in both systems
|
|
449
|
+
|
|
450
|
+
### Font files → rawfile/fonts
|
|
451
|
+
|
|
452
|
+
Copy font files from Android `font/` to HarmonyOS `rawfile/fonts/`:
|
|
453
|
+
- `.ttf`, `.otf`, `.ttc` files → direct copy
|
|
454
|
+
- Font XML files (font family definitions) → log as unmappable
|
|
455
|
+
|
|
456
|
+
---
|
|
457
|
+
|
|
458
|
+
## Qualifier Mapping
|
|
459
|
+
|
|
460
|
+
### Density Qualifiers
|
|
461
|
+
|
|
462
|
+
The naming conventions differ between Android and HarmonyOS because HarmonyOS uses different DPI range labels:
|
|
463
|
+
|
|
464
|
+
| Android Qualifier | Approx DPI | HarmonyOS Qualifier | HarmonyOS DPI Range |
|
|
465
|
+
|---|---|---|---|
|
|
466
|
+
| `ldpi` | 120 | `sdpi` | (0, 120] |
|
|
467
|
+
| `mdpi` | 160 | `mdpi` | (120, 160] |
|
|
468
|
+
| `tvdpi` | 213 | `ldpi` | (160, 240] |
|
|
469
|
+
| `hdpi` | 240 | `ldpi` | (160, 240] |
|
|
470
|
+
| `xhdpi` | 320 | `xldpi` | (240, 320] |
|
|
471
|
+
| `xxhdpi` | 480 | `xxldpi` | (320, 480] |
|
|
472
|
+
| `xxxhdpi` | 640 | `xxxldpi` | (480, 640] |
|
|
473
|
+
| `nodpi` | N/A | `base` | No density qualifier; use base |
|
|
474
|
+
| `anydpi` | N/A | `base` | No density qualifier; use base |
|
|
475
|
+
|
|
476
|
+
### Language/Region Qualifiers
|
|
477
|
+
|
|
478
|
+
Android format: `<type>-<language>` or `<type>-<language>-r<REGION>`
|
|
479
|
+
HarmonyOS format: `<language>` or `<language>_<REGION>`
|
|
480
|
+
|
|
481
|
+
**Examples:**
|
|
482
|
+
| Android | HarmonyOS |
|
|
483
|
+
|---|---|
|
|
484
|
+
| `values-ar` | `ar/element/` |
|
|
485
|
+
| `values-zh` | `zh/element/` |
|
|
486
|
+
| `values-zh-rCN` | `zh_CN/element/` |
|
|
487
|
+
| `values-zh-rTW` | `zh_TW/element/` |
|
|
488
|
+
| `values-en` | `en/element/` |
|
|
489
|
+
| `values-en-rUS` | `en_US/element/` |
|
|
490
|
+
| `values-en-rGB` | `en_GB/element/` |
|
|
491
|
+
| `values-fr-rFR` | `fr_FR/element/` |
|
|
492
|
+
| `values-ja` | `ja/element/` |
|
|
493
|
+
| `values-ko` | `ko/element/` |
|
|
494
|
+
| `drawable-zh-rCN-hdpi` | `zh_CN-ldpi/media/` |
|
|
495
|
+
|
|
496
|
+
**Parsing Android language qualifiers:**
|
|
497
|
+
- Language code: 2 or 3 lowercase letters (ISO 639)
|
|
498
|
+
- Region code: preceded by `r`, 2 uppercase letters (ISO 3166-1) — strip the `r` prefix
|
|
499
|
+
- Script code (BCP 47): preceded by `b+`, e.g., `b+sr+Latn` → `sr_Latn`
|
|
500
|
+
|
|
501
|
+
### Orientation Qualifiers
|
|
502
|
+
|
|
503
|
+
| Android | HarmonyOS |
|
|
504
|
+
|---|---|
|
|
505
|
+
| `land` | `horizontal` |
|
|
506
|
+
| `port` | `vertical` |
|
|
507
|
+
|
|
508
|
+
### Night Mode Qualifiers
|
|
509
|
+
|
|
510
|
+
| Android | HarmonyOS |
|
|
511
|
+
|---|---|
|
|
512
|
+
| `night` | `dark` |
|
|
513
|
+
| `notnight` | `light` |
|
|
514
|
+
|
|
515
|
+
### Combining Multiple Qualifiers
|
|
516
|
+
|
|
517
|
+
Android directory names can contain multiple qualifiers separated by hyphens, e.g., `drawable-zh-rCN-night-hdpi` or `mipmap-anydpi-v26`.
|
|
518
|
+
|
|
519
|
+
**Parsing algorithm for any Android resource directory name:**
|
|
520
|
+
|
|
521
|
+
1. Split the directory name by `-` to get segments
|
|
522
|
+
2. The first segment is the resource type (`drawable`, `mipmap`, `values`, etc.)
|
|
523
|
+
3. The remaining segments are qualifiers. Parse them left-to-right, recognizing:
|
|
524
|
+
- Language codes: 2-3 lowercase letters (e.g., `zh`, `ar`, `en`)
|
|
525
|
+
- Region codes: `r` + 2 uppercase letters (e.g., `rCN`, `rUS`) — always follows a language
|
|
526
|
+
- Density: `ldpi`, `mdpi`, `hdpi`, `xhdpi`, `xxhdpi`, `xxxhdpi`, `nodpi`, `anydpi`, `tvdpi`
|
|
527
|
+
- Orientation: `land`, `port`
|
|
528
|
+
- Night mode: `night`, `notnight`
|
|
529
|
+
- API level: `v` followed by digits (e.g., `v26`, `v21`) — **strip, do not reject**
|
|
530
|
+
- Screen size qualifiers: `sw<N>dp`, `w<N>dp`, `h<N>dp`, `small`, `normal`, `large`, `xlarge` — **skip entire directory, mark as unmapped**
|
|
531
|
+
- Other unsupported qualifiers — **strip, do not reject**
|
|
532
|
+
4. Map each recognized qualifier to its HarmonyOS equivalent
|
|
533
|
+
5. Strip only API-level, layout direction, screen shape, HDR, and aspect qualifiers (see "Unsupported Android Qualifiers" below)
|
|
534
|
+
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"
|
|
535
|
+
7. If no mappable or preserved qualifiers remain after stripping, use `base/`
|
|
536
|
+
8. Reassemble remaining HarmonyOS qualifiers in correct order: MCC_MNC-language_script_country/region-orientation-device-colormode-density (preserved qualifiers go at the end)
|
|
537
|
+
|
|
538
|
+
**Examples:**
|
|
539
|
+
| Android Directory | Type | Qualifiers | HarmonyOS Dir |
|
|
540
|
+
|---|---|---|---|
|
|
541
|
+
| `drawable-hdpi` | drawable | hdpi→ldpi | `ldpi/media/` |
|
|
542
|
+
| `mipmap-anydpi-v26` | mipmap | anydpi→base, v26→stripped | `base/media/` |
|
|
543
|
+
| `drawable-zh-rCN-night-hdpi` | drawable | zh-rCN→zh_CN, night→dark, hdpi→ldpi | `zh_CN-dark-ldpi/media/` |
|
|
544
|
+
| `values-ko-rKR` | values | ko-rKR→ko_KR | `ko_KR/element/` |
|
|
545
|
+
| `drawable-night-v21` | drawable | night→dark, v21→stripped | `dark/media/` |
|
|
546
|
+
|
|
547
|
+
### Unsupported Android Qualifiers
|
|
548
|
+
|
|
549
|
+
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.
|
|
550
|
+
|
|
551
|
+
Unsupported qualifiers to strip:
|
|
552
|
+
- API level `v<N>` (e.g., `v26`, `v21`, `v31`)
|
|
553
|
+
- Layout direction (`ldrtl`, `ldltr`)
|
|
554
|
+
- `round`, `notround` (screen shape)
|
|
555
|
+
- `highdr`, `lowdr` (HDR)
|
|
556
|
+
- `long`, `notlong` (screen aspect)
|
|
557
|
+
|
|
558
|
+
**Qualifiers without a HarmonyOS equivalent** (skip entirely, do NOT convert):
|
|
559
|
+
- `sw<N>dp` (smallest width, e.g., `sw600dp`)
|
|
560
|
+
- `w<N>dp` (available width, e.g., `w480dp`, `w600dp`)
|
|
561
|
+
- `h<N>dp` (available height)
|
|
562
|
+
- `small`, `normal`, `large`, `xlarge` (screen size)
|
|
563
|
+
|
|
564
|
+
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.
|
|
565
|
+
|
|
566
|
+
**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.
|
|
567
|
+
|
|
568
|
+
**Examples of stripping unsupported qualifiers:**
|
|
569
|
+
|
|
570
|
+
| Android Directory | Qualifiers Parsed | After Mapping | HarmonyOS Target |
|
|
571
|
+
|---|---|---|---|
|
|
572
|
+
| `mipmap-anydpi-v26` | `anydpi` + `v26` | `anydpi` → `base`, `v26` → stripped | `base/media/` |
|
|
573
|
+
| `drawable-night-v21` | `night` + `v21` | `night` → `dark`, `v21` → stripped | `dark/media/` |
|
|
574
|
+
| `values-sw600dp` | `sw600dp` | **skip — unmapped** | N/A (skipped) |
|
|
575
|
+
| `values-w480dp` | `w480dp` | **skip — unmapped** | N/A (skipped) |
|
|
576
|
+
| `drawable-hdpi-v4` | `hdpi` + `v4` | `hdpi` → `ldpi`, `v4` → stripped | `ldpi/media/` |
|
|
577
|
+
|
|
578
|
+
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.
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
## Special Cases and Edge Cases
|
|
583
|
+
|
|
584
|
+
### Multiple values files contributing to the same JSON
|
|
585
|
+
|
|
586
|
+
Android projects often have multiple XML files under `values/` that all contain `<string>` or `<color>` entries. For example:
|
|
587
|
+
- `values/strings.xml` — main strings
|
|
588
|
+
- `values/strings_feature.xml` — feature-specific strings
|
|
589
|
+
- `values/google_strings.xml` — library strings
|
|
590
|
+
|
|
591
|
+
All `<string>` entries from any file go into a single `string.json`. Similarly for colors, dimens, etc. Collect entries across all files before writing.
|
|
592
|
+
|
|
593
|
+
### Resource name conflicts
|
|
594
|
+
|
|
595
|
+
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.
|
|
596
|
+
|
|
597
|
+
### Android resource references
|
|
598
|
+
|
|
599
|
+
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:
|
|
600
|
+
- `@string/name` → `$string:name`
|
|
601
|
+
- `@color/name` → `$color:name`
|
|
602
|
+
- `@dimen/name` → `$float:name`
|
|
603
|
+
- `@integer/name` → `$integer:name`
|
|
604
|
+
- `@bool/name` → `$boolean:name`
|
|
605
|
+
- `?attr/name` → log as unmappable (theme attribute reference)
|
|
606
|
+
|
|
607
|
+
### Android system resource references
|
|
608
|
+
|
|
609
|
+
References like `@android:color/black` or `@android:string/ok` are Android system resources. Map known ones to literal values or HarmonyOS system resources where possible. Unknown ones should be logged in the report.
|
|
610
|
+
|
|
611
|
+
### Empty or comment-only XML files
|
|
612
|
+
|
|
613
|
+
Skip these silently — don't create empty JSON files.
|
|
614
|
+
|
|
615
|
+
### Large resource sets
|
|
616
|
+
|
|
617
|
+
When an Android project has hundreds of resources, process them systematically:
|
|
618
|
+
1. First scan and inventory all resources
|
|
619
|
+
2. Group by type and qualifier
|
|
620
|
+
3. Convert each group
|
|
621
|
+
4. Verify completeness
|
|
622
|
+
|
|
623
|
+
### XML encoding and BOM
|
|
624
|
+
|
|
625
|
+
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.
|