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,328 @@
|
|
|
1
|
+
# Android Resource Dependency Analysis Rules
|
|
2
|
+
|
|
3
|
+
This document defines how to extract, track, and resolve inter-resource dependencies during Android-to-HarmonyOS resource conversion. Dependency analysis runs regardless of resource source — whether from a decompiled APK (complete resource set) or from the project's source `res/` directory (potentially missing library resources). When working from source `res/`, more references will be unresolvable, but the analysis is still essential to identify exactly what's missing and why.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
1. [Resource Reference Patterns](#resource-reference-patterns)
|
|
7
|
+
2. [Building the Resource Value Lookup Table](#building-the-resource-value-lookup-table)
|
|
8
|
+
3. [Resolving References to True Values](#resolving-references-to-true-values)
|
|
9
|
+
4. [Where to Scan for Dependencies](#where-to-scan-for-dependencies)
|
|
10
|
+
5. [Dependency Verification](#dependency-verification)
|
|
11
|
+
6. [Handling Missing Library Resources](#handling-missing-library-resources)
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Resource Reference Patterns
|
|
16
|
+
|
|
17
|
+
Android resources reference each other using `@type/name` syntax. Extract these references from XML attribute values and text content.
|
|
18
|
+
|
|
19
|
+
### Reference Regex Pattern
|
|
20
|
+
|
|
21
|
+
Use the following pattern to extract resource references from any XML content:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
@(color|drawable|mipmap|string|dimen|integer|bool|array|style|attr|id|layout|menu|anim|animator|raw|font|xml|plurals)/([a-zA-Z_][a-zA-Z0-9_]*)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
This captures:
|
|
28
|
+
- Group 1: resource type (`color`, `drawable`, etc.)
|
|
29
|
+
- Group 2: resource name
|
|
30
|
+
|
|
31
|
+
### System Resource References
|
|
32
|
+
|
|
33
|
+
References prefixed with `@android:` (e.g., `@android:color/black`, `@android:drawable/ic_menu_close`) are Android framework resources provided by the OS. These do NOT need to be tracked as dependencies — they have no equivalent that needs to be migrated. Log them as "system resource reference" but do not flag them as unsatisfied.
|
|
34
|
+
|
|
35
|
+
### Theme Attribute References
|
|
36
|
+
|
|
37
|
+
References using `?attr/name` or `?android:attr/name` are theme attribute references resolved at runtime. These **cannot** be statically resolved — they depend on which theme is applied at runtime. Log them as "unresolvable theme attribute" and keep the reference as-is in the converted output.
|
|
38
|
+
|
|
39
|
+
### Reference Locations in XML
|
|
40
|
+
|
|
41
|
+
Resource references can appear in several places within Android XML files:
|
|
42
|
+
|
|
43
|
+
**1. XML attribute values:**
|
|
44
|
+
```xml
|
|
45
|
+
<background android:drawable="@color/md_amber_700" />
|
|
46
|
+
<TextView android:text="@string/hello" android:textColor="@color/primary" />
|
|
47
|
+
<ImageView android:src="@drawable/icon" />
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**2. Style/theme item values:**
|
|
51
|
+
```xml
|
|
52
|
+
<style name="AppTheme">
|
|
53
|
+
<item name="colorPrimary">@color/primary</item>
|
|
54
|
+
<item name="android:windowBackground">@drawable/bg_window</item>
|
|
55
|
+
</style>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**3. Color state list references:**
|
|
59
|
+
```xml
|
|
60
|
+
<selector>
|
|
61
|
+
<item android:color="@color/pressed_color" android:state_pressed="true" />
|
|
62
|
+
<item android:color="@color/default_color" />
|
|
63
|
+
</selector>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**4. Drawable XML references:**
|
|
67
|
+
```xml
|
|
68
|
+
<layer-list>
|
|
69
|
+
<item android:drawable="@drawable/bg_layer" />
|
|
70
|
+
</layer-list>
|
|
71
|
+
|
|
72
|
+
<adaptive-icon>
|
|
73
|
+
<background android:drawable="@color/ic_bg" />
|
|
74
|
+
<foreground android:drawable="@mipmap/ic_fg" />
|
|
75
|
+
</adaptive-icon>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**5. Values XML cross-references (these are the primary targets for resolution):**
|
|
79
|
+
```xml
|
|
80
|
+
<!-- colors.xml -->
|
|
81
|
+
<color name="primary_light">@color/primary</color>
|
|
82
|
+
|
|
83
|
+
<!-- dimens.xml -->
|
|
84
|
+
<color name="margin_double">@dimen/margin_base</color>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Building the Resource Value Lookup Table
|
|
90
|
+
|
|
91
|
+
Before resolving references, build a complete lookup table from the resource source directory (either decompiled `res/` or source `res/`). When using the decompiled APK, this table will be comprehensive. When using source `res/`, it will only contain app-defined resources — library resources will be absent, and references to them will be flagged during verification.
|
|
92
|
+
|
|
93
|
+
### Value Resources
|
|
94
|
+
|
|
95
|
+
Parse all `values*/*.xml` files and build mappings:
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
colors:
|
|
99
|
+
"primary" → "#FF6200EE"
|
|
100
|
+
"primary_light" → "@color/primary" # reference chain — will be resolved
|
|
101
|
+
"md_blue_500" → "#2196F3"
|
|
102
|
+
|
|
103
|
+
dimens:
|
|
104
|
+
"margin_base" → "16dp"
|
|
105
|
+
"margin_double" → "@dimen/margin_base" # reference chain
|
|
106
|
+
|
|
107
|
+
strings:
|
|
108
|
+
"app_name" → "My App"
|
|
109
|
+
"greeting" → "Hello, %1$s!"
|
|
110
|
+
|
|
111
|
+
integers:
|
|
112
|
+
"max_items" → "10"
|
|
113
|
+
|
|
114
|
+
bools:
|
|
115
|
+
"is_tablet" → "false"
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Include ALL qualifier variants (e.g., `values/colors.xml`, `values-night/colors.xml`, `values-ar/colors.xml`). Each qualifier variant gets its own entry in the lookup table.
|
|
119
|
+
|
|
120
|
+
### File Resources
|
|
121
|
+
|
|
122
|
+
Record all drawable and mipmap files:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
drawables:
|
|
126
|
+
"icon" → "drawable/icon.png"
|
|
127
|
+
"bg_card" → "drawable/bg_card.xml" (shape)
|
|
128
|
+
"ic_arrow" → "drawable/ic_arrow.xml" (vector)
|
|
129
|
+
|
|
130
|
+
mipmaps:
|
|
131
|
+
"ic_launcher" → "mipmap-anydpi-v26/ic_launcher.xml" (adaptive-icon)
|
|
132
|
+
"ic_launcher_foreground" → "mipmap-xxxhdpi/ic_launcher_foreground.png"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Resolving References to True Values
|
|
138
|
+
|
|
139
|
+
The key step: walk through all resource values and replace references with actual concrete values.
|
|
140
|
+
|
|
141
|
+
### Resolution Algorithm
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
function resolve(type, name, qualifier, depth=0):
|
|
145
|
+
if depth > 5: return UNRESOLVABLE # prevent infinite loops
|
|
146
|
+
value = lookup_table[qualifier][type][name]
|
|
147
|
+
if value is a concrete value (hex color, number, string literal):
|
|
148
|
+
return value
|
|
149
|
+
if value matches @type/other_name:
|
|
150
|
+
return resolve(type, other_name, qualifier, depth+1)
|
|
151
|
+
if value matches ?attr/name:
|
|
152
|
+
return UNRESOLVABLE # theme attribute, cannot resolve statically
|
|
153
|
+
return value
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### What Gets Resolved
|
|
157
|
+
|
|
158
|
+
**Value-to-value references** (primary targets):
|
|
159
|
+
- `@color/name` → resolved hex color (e.g., `@color/primary` → `#FF6200EE`)
|
|
160
|
+
- `@dimen/name` → resolved dimension value (e.g., `@dimen/margin_base` → `16dp`)
|
|
161
|
+
- `@string/name` → resolved string value
|
|
162
|
+
- `@integer/name` → resolved integer value
|
|
163
|
+
- `@bool/name` → resolved boolean value
|
|
164
|
+
|
|
165
|
+
**File references** (kept as HarmonyOS references, not resolved to values):
|
|
166
|
+
- `@drawable/name` → `$media:name` (the file itself is converted separately)
|
|
167
|
+
- `@mipmap/name` → `$media:name`
|
|
168
|
+
|
|
169
|
+
**Unresolvable references** (logged but kept as-is):
|
|
170
|
+
- `?attr/name` — theme attributes depend on runtime theme
|
|
171
|
+
- `@android:type/name` — system resources, provided by the platform
|
|
172
|
+
- `@style/name` — styles have no HarmonyOS equivalent
|
|
173
|
+
|
|
174
|
+
### Resolution During Conversion
|
|
175
|
+
|
|
176
|
+
Resolution happens at conversion time, not as a separate pass. When converting a value from Android XML to HarmonyOS JSON:
|
|
177
|
+
|
|
178
|
+
1. Parse the XML value
|
|
179
|
+
2. If it's a concrete value (hex color, number, string), convert directly using format rules
|
|
180
|
+
3. If it's a resource reference (`@type/name`):
|
|
181
|
+
a. Look up in the lookup table
|
|
182
|
+
b. Follow the chain to the concrete value
|
|
183
|
+
c. Convert the concrete value using format rules
|
|
184
|
+
d. Use the resolved concrete value in the HarmonyOS JSON output
|
|
185
|
+
4. If the reference can't be resolved, use HarmonyOS reference syntax (`$color:name`, `$float:name`, etc.) and log it
|
|
186
|
+
|
|
187
|
+
### Example: Full Resolution Chain
|
|
188
|
+
|
|
189
|
+
Android `values/colors.xml`:
|
|
190
|
+
```xml
|
|
191
|
+
<color name="app_background">@color/surface_color</color>
|
|
192
|
+
<color name="surface_color">@color/md_grey_50</color>
|
|
193
|
+
<color name="md_grey_50">#FAFAFA</color>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Resolution:
|
|
197
|
+
- `app_background` → `@color/surface_color` → `@color/md_grey_50` → `#FAFAFA`
|
|
198
|
+
|
|
199
|
+
HarmonyOS `color.json` output:
|
|
200
|
+
```json
|
|
201
|
+
{
|
|
202
|
+
"color": [
|
|
203
|
+
{"name": "app_background", "value": "#ffFAFAFA"},
|
|
204
|
+
{"name": "surface_color", "value": "#ffFAFAFA"},
|
|
205
|
+
{"name": "md_grey_50", "value": "#ffFAFAFA"}
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
All three resolve to the same concrete value. The `#ffFAFAFA` format is after applying the `#RRGGBB` → `#ffRRGGBB` color format conversion.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Where to Scan for Dependencies
|
|
215
|
+
|
|
216
|
+
Scan ALL resource files from the resource source directory for dependencies, organized by priority:
|
|
217
|
+
|
|
218
|
+
### High Priority (converted resources — broken dependencies cause direct errors)
|
|
219
|
+
|
|
220
|
+
| File Type | Typical Location | Why It Matters |
|
|
221
|
+
|---|---|---|
|
|
222
|
+
| Adaptive icon XML | `mipmap-anydpi-v26/*.xml` | References colors, drawables, mipmaps for icon layers |
|
|
223
|
+
| Vector drawables | `drawable/*.xml` (root: `<vector>`) | May reference colors via theme attrs |
|
|
224
|
+
| Shape drawables | `drawable/*.xml` (root: `<shape>`) | May reference colors, dimens |
|
|
225
|
+
| Layer-list drawables | `drawable/*.xml` (root: `<layer-list>`) | References other drawables |
|
|
226
|
+
| Selector drawables | `drawable/*.xml` (root: `<selector>`) | References other drawables for states |
|
|
227
|
+
| Color state lists | `color/*.xml` | References other colors |
|
|
228
|
+
| Values XML | `values*/*.xml` | Cross-references between value types |
|
|
229
|
+
|
|
230
|
+
### Required — Layout and Menu (not converted, but dependencies must be verified)
|
|
231
|
+
|
|
232
|
+
Layout and menu files are **not** converted to HarmonyOS (they use ArkUI instead), but the resources they reference — strings, colors, drawables, dimensions — **must** be present in the converted output so the developer has everything needed when rebuilding the UI.
|
|
233
|
+
|
|
234
|
+
| File Type | Typical Location | Why It Matters |
|
|
235
|
+
|---|---|---|
|
|
236
|
+
| Layout XML | `layout*/*.xml` | References strings, colors, drawables, dimens used by every UI component |
|
|
237
|
+
| Menu XML | `menu/*.xml` | References strings and drawables for action bar / navigation items |
|
|
238
|
+
|
|
239
|
+
### Skip (no meaningful dependencies)
|
|
240
|
+
|
|
241
|
+
- Raw files (`raw/`)
|
|
242
|
+
- Font files (`font/`) — unless font XML family definitions reference other fonts
|
|
243
|
+
- Image files (PNG, JPG, WEBP, etc.) — binary files, no references
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Dependency Verification
|
|
248
|
+
|
|
249
|
+
After conversion with reference resolution, verify that the output is self-consistent:
|
|
250
|
+
|
|
251
|
+
### Check by Resource Type
|
|
252
|
+
|
|
253
|
+
| Dependency Type | Where to Check in HarmonyOS Output |
|
|
254
|
+
|---|---|
|
|
255
|
+
| `@color/name` | Should be resolved to hex in `*/element/color.json`. If not resolved, check `name` exists. |
|
|
256
|
+
| `@drawable/name` | Look for `name.*` (any extension: .png, .svg, .jpg, etc.) in `*/media/` |
|
|
257
|
+
| `@mipmap/name` | Same as drawable — mipmaps go to `media/` in HarmonyOS |
|
|
258
|
+
| `@string/name` | Should be resolved to literal in `*/element/string.json`. If not resolved, check `name` exists. |
|
|
259
|
+
| `@dimen/name` | Should be resolved to value in `*/element/float.json`. If not resolved, check `name` exists. |
|
|
260
|
+
| `@integer/name` | Look for `name` in `*/element/integer.json` |
|
|
261
|
+
| `@bool/name` | Look for `name` in `*/element/boolean.json` |
|
|
262
|
+
| `@array/name` | Look for `name` in `*/element/strarray.json` or `*/element/intarray.json` |
|
|
263
|
+
| `@plurals/name` | Look for `name` in `*/element/plural.json` |
|
|
264
|
+
| `@style/name` | Mark as "unmappable type" (styles have no HarmonyOS equivalent) |
|
|
265
|
+
| `@attr/name` | Mark as "unmappable type" |
|
|
266
|
+
| `@layout/name` | Mark as "not applicable" (layouts aren't converted) |
|
|
267
|
+
| `@id/name` | Mark as "not applicable" (IDs are code-level concerns) |
|
|
268
|
+
|
|
269
|
+
### Qualifier Coverage Check
|
|
270
|
+
|
|
271
|
+
When a dependency is satisfied, also verify qualifier coverage. If the dependent resource exists in multiple qualifier directories (e.g., `base`, `dark`, `ldpi`), the dependency should ideally exist in matching qualifier directories. Flag cases where a dependency exists in `base` but the dependent resource also has `dark` or density-qualified variants — the dependency may need those variants too.
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## Handling Missing Library Resources
|
|
276
|
+
|
|
277
|
+
When converting from source `res/` (because the APK build failed or no APK was available), library-provided resources will be absent from the lookup table. This section describes how to handle these gaps gracefully.
|
|
278
|
+
|
|
279
|
+
### Identifying Library Resources
|
|
280
|
+
|
|
281
|
+
Many common Android libraries define resources with recognizable naming patterns. Use these heuristics to correlate unsatisfied dependencies with likely library sources:
|
|
282
|
+
|
|
283
|
+
| Library | Common Resource Prefixes |
|
|
284
|
+
|---|---|
|
|
285
|
+
| Material Components (`com.google.android.material`) | `material_*`, `design_*`, `mtrl_*`, `Widget.Material*`, `Theme.Material*` |
|
|
286
|
+
| AndroidX AppCompat (`androidx.appcompat`) | `abc_*`, `Widget.AppCompat.*` |
|
|
287
|
+
| AndroidX Core (`androidx.core`) | `notification_*`, `compat_*` |
|
|
288
|
+
| AndroidX ConstraintLayout | `constraint_*` |
|
|
289
|
+
| Google Play Services | `common_google_*` |
|
|
290
|
+
|
|
291
|
+
### Extracting Library Dependencies from build.gradle
|
|
292
|
+
|
|
293
|
+
Parse `build.gradle` or `build.gradle.kts` to identify declared library dependencies:
|
|
294
|
+
|
|
295
|
+
```groovy
|
|
296
|
+
// build.gradle
|
|
297
|
+
dependencies {
|
|
298
|
+
implementation 'com.google.android.material:material:1.9.0'
|
|
299
|
+
implementation 'androidx.appcompat:appcompat:1.6.1'
|
|
300
|
+
implementation 'androidx.core:core-ktx:1.12.0'
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Extract the group:artifact for each dependency. In the conversion report, list these libraries with their likely resource prefixes so the developer knows which libraries contribute which missing resources.
|
|
305
|
+
|
|
306
|
+
### Resolution Behavior for Missing Resources
|
|
307
|
+
|
|
308
|
+
When a reference cannot be resolved because the target resource is not in the lookup table:
|
|
309
|
+
|
|
310
|
+
1. **Keep the HarmonyOS reference syntax** (`$color:name`, `$float:name`, `$media:name`, etc.) in the converted output — this makes the reference visible and searchable
|
|
311
|
+
2. **Log it as an unsatisfied dependency** with:
|
|
312
|
+
- The reference (`@color/design_default_color_primary`)
|
|
313
|
+
- The source file where it was found
|
|
314
|
+
- The likely library source (if identifiable from naming patterns)
|
|
315
|
+
- The reason: "Library resource not available in source res/"
|
|
316
|
+
3. **Do NOT substitute a default or placeholder value** — keeping the reference intact is more useful because:
|
|
317
|
+
- The developer can see exactly what's missing
|
|
318
|
+
- If the build is later fixed and resources re-converted from the APK, the output will be correct
|
|
319
|
+
- The reference name itself carries meaning for the developer
|
|
320
|
+
|
|
321
|
+
### Categorizing Unresolved References
|
|
322
|
+
|
|
323
|
+
In the report, separate unresolved references into categories:
|
|
324
|
+
|
|
325
|
+
1. **Missing library resources** — references to resources that likely come from declared library dependencies. These are expected when converting from source `res/`.
|
|
326
|
+
2. **Theme attributes** (`?attr/name`) — cannot be statically resolved regardless of resource source.
|
|
327
|
+
3. **System resources** (`@android:type/name`) — Android framework resources, not migrated.
|
|
328
|
+
4. **Truly missing** — references that don't match any known library pattern and aren't in the lookup table. These may indicate a project misconfiguration or an undeclared dependency.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# Material Design Icon Download and Integration
|
|
2
|
+
|
|
3
|
+
When Android source code uses Material Design `imageVector` (such as `Icons.Outlined.Home`) to reference icons, you need to download the corresponding SVG from Google Fonts and integrate it into the HarmonyOS project.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Complete Workflow
|
|
8
|
+
|
|
9
|
+
### 1. Identify Icon References in Android Source Code
|
|
10
|
+
|
|
11
|
+
Search for icon definition files in the Android source code (usually enum classes or sealed classes) to identify two types of icons:
|
|
12
|
+
|
|
13
|
+
| Reference Type | Example | Source |
|
|
14
|
+
|---------------|---------|--------|
|
|
15
|
+
| `imageVector = Icons.Outlined.Xxx` | `Icons.Outlined.Share` | Material Design icon library, download from Google Fonts |
|
|
16
|
+
| `iconResId = R.drawable.xxx` | `R.drawable.ic_touch_enabled` | Project custom drawable, extract from Android `res/drawable/` |
|
|
17
|
+
|
|
18
|
+
**Typical Source Code Example** (Kotlin sealed class):
|
|
19
|
+
|
|
20
|
+
```kotlin
|
|
21
|
+
data object Share : ToolbarAction(
|
|
22
|
+
title = R.string.share,
|
|
23
|
+
iconResId = R.drawable.ic_share, // Custom icon
|
|
24
|
+
imageVector = Icons.Outlined.Share, // Material Design icon
|
|
25
|
+
)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
When both `iconResId` and `imageVector` exist, **prefer the Material Design icon corresponding to `imageVector`** (more standardized, clearer).
|
|
29
|
+
|
|
30
|
+
### 2. Map Icon Names
|
|
31
|
+
|
|
32
|
+
Convert `Icons.Outlined.Xxx` camelCase names from Kotlin to snake_case used by Google Fonts:
|
|
33
|
+
|
|
34
|
+
| Kotlin Name | snake_case Name | Download File Name |
|
|
35
|
+
|-------------|-----------------|-------------------|
|
|
36
|
+
| `Icons.Outlined.Share` | `share` | `md_share.svg` |
|
|
37
|
+
| `Icons.Outlined.AddHome` | `add_home` | `md_add_home.svg` |
|
|
38
|
+
| `Icons.Outlined.EditNote` | `edit_note` | `md_edit_note.svg` |
|
|
39
|
+
| `Icons.Outlined.ChromeReaderMode` | `chrome_reader_mode` | `md_chrome_reader_mode.svg` |
|
|
40
|
+
| `Icons.Outlined.LibraryBooks` | `library_books` | `md_library_books.svg` |
|
|
41
|
+
|
|
42
|
+
**Conversion Rule**: camelCase → lowercase + underscore separation (`AddHome` → `add_home`).
|
|
43
|
+
|
|
44
|
+
### 3. Download SVG
|
|
45
|
+
|
|
46
|
+
**Download source**: https://fonts.google.com/icons?icon.size=24&icon.color=%231f1f1f
|
|
47
|
+
|
|
48
|
+
**Manual download method**:
|
|
49
|
+
1. Open the Google Fonts Icons webpage above
|
|
50
|
+
2. Search for icon name (e.g., `share`, `add_home`)
|
|
51
|
+
3. Select **Outlined** style (corresponds to `Icons.Outlined`)
|
|
52
|
+
4. Click to download SVG, choose 24px size, color `#1f1f1f` (dark black)
|
|
53
|
+
|
|
54
|
+
**Download URL pattern** (can be used for batch download scripts):
|
|
55
|
+
```
|
|
56
|
+
https://fonts.gstatic.com/s/i/short-term/release/materialsymbolsoutlined/{icon_name}/default/24px.svg
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Example:
|
|
60
|
+
```
|
|
61
|
+
https://fonts.gstatic.com/s/i/short-term/release/materialsymbolsoutlined/share/default/24px.svg
|
|
62
|
+
https://fonts.gstatic.com/s/i/short-term/release/materialsymbolsoutlined/add_home/default/24px.svg
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Note**:
|
|
66
|
+
- The SVG downloaded from this URL has `fill="#000000"` (pure black)
|
|
67
|
+
- Downloaded SVG size is `viewBox="0 -960 960 960"` (Google standard Material Symbols coordinate system), renders correctly in HarmonyOS
|
|
68
|
+
- If an icon name doesn't exist in `materialsymbolsoutlined`, try `materialsymbolsrounded` or `materialsymbolssharp`
|
|
69
|
+
|
|
70
|
+
### 4. Rename and Store
|
|
71
|
+
|
|
72
|
+
**Naming rule**: Add `md_` prefix + snake_case name uniformly
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
Downloaded share.svg → md_share.svg
|
|
76
|
+
Downloaded add_home.svg → md_add_home.svg
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Storage location**: `entry/src/main/resources/base/media/`
|
|
80
|
+
|
|
81
|
+
**Key constraints**:
|
|
82
|
+
- `media/` directory **does not support subdirectories** (e.g., `media/icons/` will cause `CompileResource` error "invalid path, not a file")
|
|
83
|
+
- File names only allow lowercase letters, numbers, underscores
|
|
84
|
+
- All icon files must be placed directly at the root level of `media/` directory
|
|
85
|
+
|
|
86
|
+
### 5. Reference in ArkTS
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
// Reference method: $r('app.media.filename_without_extension')
|
|
90
|
+
Image($r('app.media.md_share'))
|
|
91
|
+
Image($r('app.media.md_add_home'))
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Typical icon mapping function pattern:
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
private getIconResource(action: string): Resource {
|
|
98
|
+
switch (action) {
|
|
99
|
+
case 'share':
|
|
100
|
+
return $r('app.media.md_share')
|
|
101
|
+
case 'add_home':
|
|
102
|
+
return $r('app.media.md_add_home')
|
|
103
|
+
case 'settings':
|
|
104
|
+
return $r('app.media.md_settings')
|
|
105
|
+
default:
|
|
106
|
+
return $r('app.media.icon_default')
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Batch Download Script Example
|
|
114
|
+
|
|
115
|
+
Python script for batch downloading multiple icons:
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
import urllib.request
|
|
119
|
+
import os
|
|
120
|
+
|
|
121
|
+
icons = [
|
|
122
|
+
'share', 'add_home', 'edit_note', 'logout', 'bookmark_add',
|
|
123
|
+
'add_link', 'apps', 'copy_all', 'library_books', 'pdf',
|
|
124
|
+
'download', 'rule_settings', 'settings', 'chrome_reader_mode',
|
|
125
|
+
'record_voice_over', 'invert_colors', 'format_size', 'view_column',
|
|
126
|
+
'chat', 'cancel_presentation', 'cloud_upload', 'bookmarks'
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
output_dir = 'material_icons_svg'
|
|
130
|
+
os.makedirs(output_dir, exist_ok=True)
|
|
131
|
+
|
|
132
|
+
base_url = 'https://fonts.gstatic.com/s/i/short-term/release/materialsymbolsoutlined/{}/default/24px.svg'
|
|
133
|
+
|
|
134
|
+
for icon in icons:
|
|
135
|
+
url = base_url.format(icon)
|
|
136
|
+
out_path = os.path.join(output_dir, f'md_{icon}.svg')
|
|
137
|
+
try:
|
|
138
|
+
urllib.request.urlretrieve(url, out_path)
|
|
139
|
+
print(f'OK: {icon}')
|
|
140
|
+
except Exception as e:
|
|
141
|
+
print(f'FAIL: {icon} - {e}')
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Common Icon Mapping Reference
|
|
147
|
+
|
|
148
|
+
Typical Material Design icon mappings for Android toolbar/menu items:
|
|
149
|
+
|
|
150
|
+
| Kotlin imageVector | snake_case Name | Download SVG | HarmonyOS Reference |
|
|
151
|
+
|-------------------|-----------------|-------------|---------------------|
|
|
152
|
+
| `Icons.Outlined.Share` | `share` | `md_share.svg` | `$r('app.media.md_share')` |
|
|
153
|
+
| `Icons.Outlined.Settings` | `settings` | `md_settings.svg` | `$r('app.media.md_settings')` |
|
|
154
|
+
| `Icons.Outlined.Home` | `home` | `md_home.svg` | `$r('app.media.md_home')` |
|
|
155
|
+
| `Icons.Outlined.Add` | `add` | `md_add.svg` | `$r('app.media.md_add')` |
|
|
156
|
+
| `Icons.Outlined.Edit` | `edit` | `md_edit.svg` | `$r('app.media.md_edit')` |
|
|
157
|
+
| `Icons.Outlined.Delete` | `delete` | `md_delete.svg` | `$r('app.media.md_delete')` |
|
|
158
|
+
| `Icons.Outlined.Search` | `search` | `md_search.svg` | `$r('app.media.md_search')` |
|
|
159
|
+
| `Icons.Outlined.ArrowBack` | `arrow_back` | `md_arrow_back.svg` | `$r('app.media.md_arrow_back')` |
|
|
160
|
+
| `Icons.Outlined.Bookmark` | `bookmark` | `md_bookmark.svg` | `$r('app.media.md_bookmark')` |
|
|
161
|
+
| `Icons.Outlined.BookmarkAdd` | `bookmark_add` | `md_bookmark_add.svg` | `$r('app.media.md_bookmark_add')` |
|
|
162
|
+
| `Icons.Outlined.Favorite` | `favorite` | `md_favorite.svg` | `$r('app.media.md_favorite')` |
|
|
163
|
+
| `Icons.Outlined.Share` | `share` | `md_share.svg` | `$r('app.media.md_share')` |
|
|
164
|
+
| `Icons.Outlined.Download` | `download` | `md_download.svg` | `$r('app.media.md_download')` |
|
|
165
|
+
| `Icons.Outlined.Upload` | `upload` | `md_upload.svg` | `$r('app.media.md_upload')` |
|
|
166
|
+
| `Icons.Outlined.Refresh` | `refresh` | `md_refresh.svg` | `$r('app.media.md_refresh')` |
|
|
167
|
+
| `Icons.Outlined.Menu` | `menu` | `md_menu.svg` | `$r('app.media.md_menu')` |
|
|
168
|
+
| `Icons.Outlined.MoreVert` | `more_vert` | `md_more_vert.svg` | `$r('app.media.md_more_vert')` |
|
|
169
|
+
| `Icons.Outlined.Close` | `close` | `md_close.svg` | `$r('app.media.md_close')` |
|
|
170
|
+
| `Icons.Outlined.Check` | `check` | `md_check.svg` | `$r('app.media.md_check')` |
|
|
171
|
+
| `Icons.Outlined.Visibility` | `visibility` | `md_visibility.svg` | `$r('app.media.md_visibility')` |
|
|
172
|
+
|
|
173
|
+
Note: `Icons.AutoMirrored.Outlined.*` variants use the same icon name as their non-mirrored counterparts (e.g., `Icons.AutoMirrored.Outlined.ArrowBack` → `arrow_back`).
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# SVG Display Issue Fix Patterns
|
|
2
|
+
|
|
3
|
+
Common display abnormalities and fixes when migrating SVG/Vector Drawables from Android projects or manually creating SVGs.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Issue 1: viewBox Does Not Match Path Coordinates
|
|
8
|
+
|
|
9
|
+
### Symptoms
|
|
10
|
+
Icon does not display at all, or only shows a blank area.
|
|
11
|
+
|
|
12
|
+
### Cause
|
|
13
|
+
The coordinate range defined by `viewBox` does not match the coordinate data in the `d` attribute of `<path>`.
|
|
14
|
+
|
|
15
|
+
For example: path data is based on a 512×512 coordinate system (coordinate values range from 85 to 448), but `viewBox` is set to `0 0 24 24`, causing all paths to exceed the visible area.
|
|
16
|
+
|
|
17
|
+
### Fix
|
|
18
|
+
|
|
19
|
+
**Option A: Adjust viewBox to Match Path Coordinates (Recommended for Simple Cases)**
|
|
20
|
+
```xml
|
|
21
|
+
<!-- Wrong: viewBox too small -->
|
|
22
|
+
<svg viewBox="0 0 24 24">
|
|
23
|
+
<path d="M101.51,411.23 Q85.21,395.05 ..." /> <!-- coordinates far exceed 24 -->
|
|
24
|
+
</svg>
|
|
25
|
+
|
|
26
|
+
<!-- Fixed: viewBox matches coordinate system, use width/height to control render size -->
|
|
27
|
+
<svg width="24" height="24" viewBox="0 0 512 512">
|
|
28
|
+
<path d="M101.51,411.23 Q85.21,395.05 ..." />
|
|
29
|
+
</svg>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
> Note: `viewBox` defines the path coordinate space, while `width`/`height` define the render size. They are independent.
|
|
33
|
+
|
|
34
|
+
**Option B: Scale Path Coordinates Proportionally (Recommended for Standardization)**
|
|
35
|
+
|
|
36
|
+
Scale all values in the path proportionally to the target coordinate system. For example, scaling from 512 to 24:
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
import re
|
|
40
|
+
|
|
41
|
+
scale = 24.0 / 512.0 # 0.046875
|
|
42
|
+
|
|
43
|
+
def scale_number(match):
|
|
44
|
+
num = float(match.group(0))
|
|
45
|
+
scaled = round(num * scale, 2)
|
|
46
|
+
return '{:.2f}'.format(scaled).rstrip('0').rstrip('.')
|
|
47
|
+
|
|
48
|
+
path_data = "M101.51,411.23Q85.21,395.05 85.22,371.75..."
|
|
49
|
+
result = re.sub(r'[0-9]+\.?[0-9]*', scale_number, path_data)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
After scaling, you can use the standard `viewBox="0 0 24 24"`, consistent with other Material Design icons.
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Issue 2: Android Vector Drawable Syntax Remnants
|
|
57
|
+
|
|
58
|
+
### Symptoms
|
|
59
|
+
The SVG file contains Android-specific XML attributes that standard SVG renderers cannot parse.
|
|
60
|
+
|
|
61
|
+
### Common Remnant Syntax
|
|
62
|
+
|
|
63
|
+
| Android Syntax | Standard SVG Equivalent |
|
|
64
|
+
|---------------|----------------------|
|
|
65
|
+
| `<group android:translateX="24" android:rotation="90">` | `<g transform="translate(24,0) rotate(90)">` |
|
|
66
|
+
| `android:fillColor="#FF000000"` | `fill="#000000"` |
|
|
67
|
+
| `android:pathData="..."` | `d="..."` |
|
|
68
|
+
| `android:viewportWidth="24"` | Part of `viewBox="0 0 24 24"` |
|
|
69
|
+
| `<vector>` root element | `<svg>` root element |
|
|
70
|
+
| `<clip-path android:pathData="..."/>` | `<defs><clipPath id="..."><path d="..."/></clipPath></defs>` |
|
|
71
|
+
|
|
72
|
+
### Fix
|
|
73
|
+
|
|
74
|
+
Fully convert Android `<group>` transform attributes to SVG `transform`:
|
|
75
|
+
|
|
76
|
+
```xml
|
|
77
|
+
<!-- Android Vector Drawable -->
|
|
78
|
+
<group
|
|
79
|
+
android:translateX="24"
|
|
80
|
+
android:translateY="0"
|
|
81
|
+
android:rotation="90"
|
|
82
|
+
android:pivotX="12"
|
|
83
|
+
android:pivotY="12"
|
|
84
|
+
android:scaleX="1.5"
|
|
85
|
+
android:scaleY="1.5">
|
|
86
|
+
<path android:pathData="M18,12l4,-4..." android:fillColor="#FFFFFF"/>
|
|
87
|
+
</group>
|
|
88
|
+
|
|
89
|
+
<!-- Converted to Standard SVG -->
|
|
90
|
+
<g transform="translate(24,0) rotate(90,12,12) scale(1.5,1.5)">
|
|
91
|
+
<path d="M18,12l4,-4..." fill="#FFFFFF"/>
|
|
92
|
+
</g>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Transform order: `translate` → `rotate` (with pivot point) → `scale`
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Issue 3: Fill Color is White Causing Invisible Icon
|
|
100
|
+
|
|
101
|
+
### Symptoms
|
|
102
|
+
SVG file exists and path is correct, but icon does not display (invisible on white background).
|
|
103
|
+
|
|
104
|
+
### Cause
|
|
105
|
+
The original Android drawable's `fillColor` is `#FFFFFF` (white), which is invisible on a white background. Common for icons designed to appear on dark ActionBars.
|
|
106
|
+
|
|
107
|
+
### Fix
|
|
108
|
+
|
|
109
|
+
Change `fill="#FFFFFF"` to `fill="#000000"` (black), or choose a suitable color based on UI needs:
|
|
110
|
+
|
|
111
|
+
```xml
|
|
112
|
+
<!-- Before fix: white fill invisible on white background -->
|
|
113
|
+
<path fill="#FFFFFF" d="M18,12l4,-4..."/>
|
|
114
|
+
|
|
115
|
+
<!-- After fix -->
|
|
116
|
+
<path fill="#000000" d="M18,12l4,-4..."/>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Issue 4: Google Material Symbols Coordinate System
|
|
122
|
+
|
|
123
|
+
### Description
|
|
124
|
+
Material Symbols SVGs downloaded from Google Fonts use a special coordinate system:
|
|
125
|
+
|
|
126
|
+
```xml
|
|
127
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#000000">
|
|
128
|
+
<path d="M200-120q-33 0-56.5-23.5T120-200v-560..."/>
|
|
129
|
+
</svg>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
- `viewBox="0 -960 960 960"` — Y-axis starts at -960 (positive is upward)
|
|
133
|
+
- Many negative values in path coordinates are normal
|
|
134
|
+
- This format renders correctly in HarmonyOS, **no additional conversion needed**
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Issue 5: HarmonyOS media Directory Does Not Support Subdirectories
|
|
139
|
+
|
|
140
|
+
### Symptoms
|
|
141
|
+
Compilation error: `CompileResource` error "invalid path, not a file"
|
|
142
|
+
|
|
143
|
+
### Cause
|
|
144
|
+
Created subdirectories under `resources/base/media/` (e.g., `media/icons/`, `media/md/`).
|
|
145
|
+
|
|
146
|
+
### Fix
|
|
147
|
+
|
|
148
|
+
Move all files from subdirectories to the `media/` root directory, using file name prefixes to distinguish sources:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# Wrong: using subdirectories
|
|
152
|
+
media/
|
|
153
|
+
md/
|
|
154
|
+
share.svg
|
|
155
|
+
home.svg
|
|
156
|
+
|
|
157
|
+
# Correct: flat storage with prefixes
|
|
158
|
+
media/
|
|
159
|
+
md_share.svg
|
|
160
|
+
md_home.svg
|
|
161
|
+
ic_custom_icon.svg
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Quick Diagnosis Checklist
|
|
167
|
+
|
|
168
|
+
When SVG icon does not display, check in order:
|
|
169
|
+
|
|
170
|
+
1. **File exists?** — Confirm the file exists under `entry/src/main/resources/base/media/`
|
|
171
|
+
2. **Reference correct?** — `$r('app.media.filename_without_extension')`, filename is case-sensitive
|
|
172
|
+
3. **viewBox matches?** — `viewBox` coordinate range must cover path data coordinate values
|
|
173
|
+
4. **Syntax standard?** — No `android:` namespace attributes, root element is `<svg>` not `<vector>`
|
|
174
|
+
5. **Fill color visible?** — `fill` is not `#FFFFFF` (invisible on white background)
|
|
175
|
+
6. **No subdirectories?** — SVG files are directly under `media/` root directory
|