packwise-skills 1.0.0 → 1.2.0

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.
Files changed (53) hide show
  1. package/.cursorrules +23 -23
  2. package/CLAUDE.md +25 -25
  3. package/LICENSE +21 -0
  4. package/README.md +404 -295
  5. package/audit.md +224 -224
  6. package/bin/packwise.js +322 -155
  7. package/install.sh +123 -0
  8. package/package.json +32 -31
  9. package/skill.md +944 -719
  10. package/sub-skills/ai/local-llm.md +183 -183
  11. package/sub-skills/ai/python-ml.md +164 -164
  12. package/sub-skills/backend/go-server.md +184 -184
  13. package/sub-skills/backend/java-spring.md +241 -241
  14. package/sub-skills/backend/node-server.md +164 -164
  15. package/sub-skills/backend/php-laravel.md +175 -175
  16. package/sub-skills/backend/python-server.md +164 -164
  17. package/sub-skills/backend/rust-backend.md +118 -118
  18. package/sub-skills/cli/python-cli.md +236 -236
  19. package/sub-skills/cli/sdk-library.md +497 -497
  20. package/sub-skills/cloud/ci-cd-pipelines.md +350 -350
  21. package/sub-skills/cloud/docker.md +191 -191
  22. package/sub-skills/cloud/kubernetes.md +277 -277
  23. package/sub-skills/cloud/payment-integration.md +307 -307
  24. package/sub-skills/cross-platform/multiplatform.md +252 -252
  25. package/sub-skills/desktop/electron.md +783 -783
  26. package/sub-skills/desktop/game-dev.md +443 -443
  27. package/sub-skills/desktop/native-app.md +123 -123
  28. package/sub-skills/desktop/scenarios.md +443 -443
  29. package/sub-skills/desktop/smart-platforms.md +324 -324
  30. package/sub-skills/desktop/tauri.md +428 -428
  31. package/sub-skills/desktop/vr-ar.md +252 -252
  32. package/sub-skills/desktop/web-to-desktop.md +153 -153
  33. package/sub-skills/embedded/car-infotainment.md +129 -129
  34. package/sub-skills/embedded/esp32.md +184 -184
  35. package/sub-skills/embedded/ros.md +150 -150
  36. package/sub-skills/embedded/stm32.md +160 -160
  37. package/sub-skills/mobile/android.md +322 -322
  38. package/sub-skills/mobile/capacitor.md +232 -232
  39. package/sub-skills/mobile/flutter-mobile.md +138 -138
  40. package/sub-skills/mobile/harmonyos.md +150 -150
  41. package/sub-skills/mobile/ios.md +245 -245
  42. package/sub-skills/mobile/react-native.md +443 -443
  43. package/sub-skills/mobile/wearables.md +230 -230
  44. package/sub-skills/plugins/browser-extension.md +308 -308
  45. package/sub-skills/plugins/jetbrains-plugin.md +226 -226
  46. package/sub-skills/plugins/vscode-extension.md +204 -204
  47. package/sub-skills/security/security-tools.md +174 -174
  48. package/sub-skills/web/monorepo.md +274 -274
  49. package/sub-skills/web/pwa.md +220 -220
  50. package/sub-skills/web/serverless-edge.md +295 -295
  51. package/sub-skills/web/spa.md +266 -266
  52. package/sub-skills/web/ssr.md +228 -228
  53. package/sub-skills/web/wasm.md +243 -243
@@ -1,322 +1,322 @@
1
- # Android Native Build Sub-Skill
2
-
3
- Build and publish Kotlin/Java native Android applications.
4
-
5
- **Current version**: Android 15 (API 35) / AGP 8.7.x / Gradle 8.10+ / JDK 17 (2025-2026)
6
-
7
- ## When to Use
8
-
9
- - Native Android applications (Kotlin recommended, Java supported)
10
- - Apps requiring deep Android platform integration
11
- - Apps published to Google Play, Huawei AppGallery, or Xiaomi GetApps
12
-
13
- ## Prerequisites
14
-
15
- ```bash
16
- # JDK 17 (REQUIRED for AGP 8.x)
17
- # Android Studio (includes JDK 17 bundled as JBR)
18
- # OR: standalone JDK 17
19
-
20
- # Android SDK 35 (via Android Studio SDK Manager)
21
- # NDK (if using native code)
22
-
23
- # Verify
24
- java -version # Should show 17.x
25
- ```
26
-
27
- ## Build
28
-
29
- ```bash
30
- ./gradlew assembleDebug # Debug APK
31
- ./gradlew assembleRelease # Release APK
32
- ./gradlew bundleRelease # AAB (required by Google Play)
33
- ```
34
-
35
- ## Required Build Configuration (AGP 8.x)
36
-
37
- ```kotlin
38
- // build.gradle.kts (app-level)
39
- android {
40
- namespace = "com.example.myapp" // REQUIRED since AGP 8.0 (replaces package in AndroidManifest)
41
- compileSdk = 35 // Should match latest API level
42
-
43
- defaultConfig {
44
- applicationId = "com.example.myapp"
45
- minSdk = 24 // Android 7.0
46
- targetSdk = 35 // REQUIRED: Google Play mandates API 35 as of 2025
47
- versionCode = 1
48
- versionName = "1.0.0"
49
- }
50
- }
51
- ```
52
-
53
- ```xml
54
- <!-- AndroidManifest.xml — REMOVE package attribute (AGP 8.x) -->
55
- <manifest xmlns:android="http://schemas.android.com/apk/res/android">
56
- <!-- NO package="..." attribute here -->
57
- </manifest>
58
- ```
59
-
60
- ### gradle.properties (Modern Defaults)
61
-
62
- ```properties
63
- # gradle.properties
64
- android.useAndroidX=true
65
- android.nonTransitiveRClass=true
66
- org.gradle.jvmargs=-Xmx4g -XX:+UseG1GC
67
- org.gradle.parallel=true
68
- org.gradle.caching=true
69
- org.gradle.configuration-cache=true
70
- ```
71
-
72
- ## Signing (Secure Approach)
73
-
74
- ### Generate Upload Key
75
-
76
- ```bash
77
- keytool -genkey -v -keystore upload-key.jks \
78
- -keyalg RSA -keysize 2048 -validity 10000 \
79
- -alias upload
80
- ```
81
-
82
- ### Secure Signing Configuration
83
-
84
- ```kotlin
85
- // build.gradle.kts — NEVER hardcode passwords
86
- signingConfigs {
87
- create("release") {
88
- storeFile = file(System.getenv("KEYSTORE_PATH") ?: "../keystore/upload-key.jks")
89
- storePassword = System.getenv("KEYSTORE_PASSWORD") ?: ""
90
- keyAlias = System.getenv("KEY_ALIAS") ?: ""
91
- keyPassword = System.getenv("KEY_PASSWORD") ?: ""
92
- }
93
- }
94
-
95
- buildTypes {
96
- release {
97
- signingConfig = signingConfigs.getByName("release")
98
- isMinifyEnabled = true
99
- isShrinkResources = true
100
- proguardFiles(
101
- getDefaultProguardFile("proguard-android-optimize.txt"),
102
- "proguard-rules.pro"
103
- )
104
- }
105
- }
106
- ```
107
-
108
- ### Play App Signing (Recommended)
109
-
110
- Google Play App Signing separates the **upload key** (you hold) from the **signing key** (Google holds):
111
-
112
- - **Upload key**: Signs your AAB before uploading. If lost, can be reset in Play Console.
113
- - **Signing key**: Signs the final APK delivered to users. Google manages this securely.
114
- - Enroll in Google Play Console → Release → Setup → App signing
115
-
116
- ## 16KB Page Alignment (Android 15 Requirement)
117
-
118
- Android 15 devices may use 16KB memory pages. All native libraries (.so files) must be 16KB aligned.
119
-
120
- ```kotlin
121
- // build.gradle.kts
122
- android {
123
- packaging {
124
- jniLibs {
125
- pageAlignSharedLibs = true // AGP 8.5+
126
- }
127
- }
128
- }
129
- ```
130
-
131
- ```bash
132
- # Check alignment
133
- unzip -l app.apk | grep "\.so$"
134
- ```
135
-
136
- **Apps without native code are NOT affected.**
137
-
138
- ## Network Security Config
139
-
140
- ```xml
141
- <!-- res/xml/network_security_config.xml -->
142
- <?xml version="1.0" encoding="utf-8"?>
143
- <network-security-config>
144
- <base-config cleartextTrafficPermitted="false">
145
- <trust-anchors>
146
- <certificates src="system" />
147
- </trust-anchors>
148
- </base-config>
149
- </network-security-config>
150
- ```
151
-
152
- ```xml
153
- <!-- AndroidManifest.xml -->
154
- <application
155
- android:networkSecurityConfig="@xml/network_security_config"
156
- ... >
157
- ```
158
-
159
- ## Android Keystore (Runtime Key Storage)
160
-
161
- For storing sensitive data at runtime (tokens, credentials), use Android Keystore — NOT JKS files:
162
-
163
- ```kotlin
164
- // EncryptedSharedPreferences (recommended for key-value storage)
165
- val masterKey = MasterKey.Builder(context)
166
- .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
167
- .build()
168
-
169
- val securePrefs = EncryptedSharedPreferences.create(
170
- context, "secret_prefs", masterKey,
171
- EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
172
- EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
173
- )
174
- ```
175
-
176
- ## Foreground Service Types (Android 14+)
177
-
178
- Starting with Android 14 (API 34), every foreground service MUST declare a type:
179
-
180
- ```xml
181
- <service
182
- android:name=".MyService"
183
- android:foregroundServiceType="dataSync" />
184
- ```
185
-
186
- Valid types: `camera`, `connectedDevice`, `dataSync`, `health`, `location`, `mediaPlayback`, `microphone`, `phoneCall`, `shortService`, `specialUse`.
187
-
188
- ## Permissions Policy
189
-
190
- ```xml
191
- <!-- Android 13+ notification permission -->
192
- <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
193
-
194
- <!-- Android 13+ granular media permissions (replaces READ_EXTERNAL_STORAGE) -->
195
- <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
196
- <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
197
-
198
- <!-- Use system photo picker instead of READ_MEDIA_IMAGES when possible -->
199
- <!-- No permission needed: ActivityResultContracts.PickVisualMedia() -->
200
- ```
201
-
202
- ## Store Publishing Checklist
203
-
204
- | Step | Description |
205
- |------|-------------|
206
- | 1. Register developer | Google Play ($25 one-time), Huawei (free), Xiaomi (free) |
207
- | 2. Generate signed AAB | `./gradlew bundleRelease` |
208
- | 3. Privacy policy | Required URL — must be accessible without login |
209
- | 4. Data Safety section | Declare all data collection in Play Console (Mandatory) |
210
- | 5. Data deletion | Apps with account creation MUST provide data deletion option |
211
- | 6. App icon | 512x512 PNG |
212
- | 7. Screenshots | Phone + tablet |
213
- | 8. Description | App name, short description, full description |
214
- | 9. Content rating | IARC rating questionnaire |
215
- | 10. Target SDK | Must be API 35 (as of 2025/2026) |
216
- | 11. Submit review | Google Play typically 1–3 days |
217
-
218
- ## Build Optimization
219
-
220
- ### ABI Splits (Reduce APK Size)
221
-
222
- ```kotlin
223
- // build.gradle.kts
224
- android {
225
- splits {
226
- abi {
227
- isEnable = true
228
- reset()
229
- include("arm64-v8a", "armeabi-v7a", "x86_64")
230
- isUniversalApk = false
231
- }
232
- }
233
- }
234
- ```
235
-
236
- ### R8 Code Shrinking
237
-
238
- ```kotlin
239
- // build.gradle.kts
240
- android {
241
- buildTypes {
242
- release {
243
- isMinifyEnabled = true
244
- isShrinkResources = true
245
- proguardFiles(
246
- getDefaultProguardFile("proguard-android-optimize.txt"),
247
- "proguard-rules.pro"
248
- )
249
- }
250
- }
251
- }
252
- ```
253
-
254
- ### Build Variant Management
255
-
256
- ```kotlin
257
- // build.gradle.kts
258
- android {
259
- flavorDimensions += "env"
260
- productFlavors {
261
- create("dev") {
262
- dimension = "env"
263
- applicationIdSuffix = ".dev"
264
- versionNameSuffix = "-dev"
265
- }
266
- create("staging") {
267
- dimension = "env"
268
- applicationIdSuffix = ".staging"
269
- }
270
- create("prod") {
271
- dimension = "env"
272
- }
273
- }
274
- }
275
- ```
276
-
277
- ## CI/CD — GitHub Actions
278
-
279
- ```yaml
280
- name: Android Build
281
- on:
282
- push:
283
- tags: ['v*']
284
- jobs:
285
- build:
286
- runs-on: ubuntu-latest
287
- steps:
288
- - uses: actions/checkout@v4
289
- - uses: actions/setup-java@v4
290
- with:
291
- distribution: 'temurin'
292
- java-version: '17'
293
- - name: Decode Keystore
294
- run: echo "${{ secrets.RELEASE_KEYSTORE_BASE64 }}" | base64 --decode > app/release.jks
295
- - name: Build AAB
296
- env:
297
- KEYSTORE_PATH: release.jks
298
- KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
299
- KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
300
- KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
301
- run: ./gradlew bundleRelease
302
- - uses: actions/upload-artifact@v4
303
- with:
304
- name: aab
305
- path: app/build/outputs/bundle/release/*.aab
306
- ```
307
-
308
- ## Common Pitfalls
309
-
310
- | Issue | Fix |
311
- |-------|-----|
312
- | "Namespace not specified" | Add `namespace = "com.example.app"` in build.gradle (AGP 8.x requires it) |
313
- | Signing error | Check environment variables; never hardcode passwords |
314
- | ProGuard crash | Add `-keep` rules for models, native modules, serialization |
315
- | Target SDK rejected | Google Play requires `targetSdk = 35` as of 2025 |
316
- | 16KB alignment error | Add `pageAlignSharedLibs = true` in build.gradle |
317
- | Foreground service crash | Declare `foregroundServiceType` in AndroidManifest (API 34+) |
318
- | Data Safety rejection | Complete Data Safety section in Play Console |
319
- | Privacy policy rejected | URL must be live, accessible without login, match Data Safety declaration |
320
- | Cleartext traffic blocked | Android 9+ blocks HTTP by default; use HTTPS or configure network_security_config |
321
- | `READ_EXTERNAL_STORAGE` not working | Android 13+ uses `READ_MEDIA_IMAGES`/`READ_MEDIA_VIDEO` instead |
322
- | Play App Signing key lost | Upload key can be reset in Play Console; signing key is managed by Google |
1
+ # Android Native Build Sub-Skill
2
+
3
+ Build and publish Kotlin/Java native Android applications.
4
+
5
+ **Current version**: Android 15 (API 35) / AGP 8.7.x / Gradle 8.10+ / JDK 17 (2025-2026)
6
+
7
+ ## When to Use
8
+
9
+ - Native Android applications (Kotlin recommended, Java supported)
10
+ - Apps requiring deep Android platform integration
11
+ - Apps published to Google Play, Huawei AppGallery, or Xiaomi GetApps
12
+
13
+ ## Prerequisites
14
+
15
+ ```bash
16
+ # JDK 17 (REQUIRED for AGP 8.x)
17
+ # Android Studio (includes JDK 17 bundled as JBR)
18
+ # OR: standalone JDK 17
19
+
20
+ # Android SDK 35 (via Android Studio SDK Manager)
21
+ # NDK (if using native code)
22
+
23
+ # Verify
24
+ java -version # Should show 17.x
25
+ ```
26
+
27
+ ## Build
28
+
29
+ ```bash
30
+ ./gradlew assembleDebug # Debug APK
31
+ ./gradlew assembleRelease # Release APK
32
+ ./gradlew bundleRelease # AAB (required by Google Play)
33
+ ```
34
+
35
+ ## Required Build Configuration (AGP 8.x)
36
+
37
+ ```kotlin
38
+ // build.gradle.kts (app-level)
39
+ android {
40
+ namespace = "com.example.myapp" // REQUIRED since AGP 8.0 (replaces package in AndroidManifest)
41
+ compileSdk = 35 // Should match latest API level
42
+
43
+ defaultConfig {
44
+ applicationId = "com.example.myapp"
45
+ minSdk = 24 // Android 7.0
46
+ targetSdk = 35 // REQUIRED: Google Play mandates API 35 as of 2025
47
+ versionCode = 1
48
+ versionName = "1.0.0"
49
+ }
50
+ }
51
+ ```
52
+
53
+ ```xml
54
+ <!-- AndroidManifest.xml — REMOVE package attribute (AGP 8.x) -->
55
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
56
+ <!-- NO package="..." attribute here -->
57
+ </manifest>
58
+ ```
59
+
60
+ ### gradle.properties (Modern Defaults)
61
+
62
+ ```properties
63
+ # gradle.properties
64
+ android.useAndroidX=true
65
+ android.nonTransitiveRClass=true
66
+ org.gradle.jvmargs=-Xmx4g -XX:+UseG1GC
67
+ org.gradle.parallel=true
68
+ org.gradle.caching=true
69
+ org.gradle.configuration-cache=true
70
+ ```
71
+
72
+ ## Signing (Secure Approach)
73
+
74
+ ### Generate Upload Key
75
+
76
+ ```bash
77
+ keytool -genkey -v -keystore upload-key.jks \
78
+ -keyalg RSA -keysize 2048 -validity 10000 \
79
+ -alias upload
80
+ ```
81
+
82
+ ### Secure Signing Configuration
83
+
84
+ ```kotlin
85
+ // build.gradle.kts — NEVER hardcode passwords
86
+ signingConfigs {
87
+ create("release") {
88
+ storeFile = file(System.getenv("KEYSTORE_PATH") ?: "../keystore/upload-key.jks")
89
+ storePassword = System.getenv("KEYSTORE_PASSWORD") ?: ""
90
+ keyAlias = System.getenv("KEY_ALIAS") ?: ""
91
+ keyPassword = System.getenv("KEY_PASSWORD") ?: ""
92
+ }
93
+ }
94
+
95
+ buildTypes {
96
+ release {
97
+ signingConfig = signingConfigs.getByName("release")
98
+ isMinifyEnabled = true
99
+ isShrinkResources = true
100
+ proguardFiles(
101
+ getDefaultProguardFile("proguard-android-optimize.txt"),
102
+ "proguard-rules.pro"
103
+ )
104
+ }
105
+ }
106
+ ```
107
+
108
+ ### Play App Signing (Recommended)
109
+
110
+ Google Play App Signing separates the **upload key** (you hold) from the **signing key** (Google holds):
111
+
112
+ - **Upload key**: Signs your AAB before uploading. If lost, can be reset in Play Console.
113
+ - **Signing key**: Signs the final APK delivered to users. Google manages this securely.
114
+ - Enroll in Google Play Console → Release → Setup → App signing
115
+
116
+ ## 16KB Page Alignment (Android 15 Requirement)
117
+
118
+ Android 15 devices may use 16KB memory pages. All native libraries (.so files) must be 16KB aligned.
119
+
120
+ ```kotlin
121
+ // build.gradle.kts
122
+ android {
123
+ packaging {
124
+ jniLibs {
125
+ pageAlignSharedLibs = true // AGP 8.5+
126
+ }
127
+ }
128
+ }
129
+ ```
130
+
131
+ ```bash
132
+ # Check alignment
133
+ unzip -l app.apk | grep "\.so$"
134
+ ```
135
+
136
+ **Apps without native code are NOT affected.**
137
+
138
+ ## Network Security Config
139
+
140
+ ```xml
141
+ <!-- res/xml/network_security_config.xml -->
142
+ <?xml version="1.0" encoding="utf-8"?>
143
+ <network-security-config>
144
+ <base-config cleartextTrafficPermitted="false">
145
+ <trust-anchors>
146
+ <certificates src="system" />
147
+ </trust-anchors>
148
+ </base-config>
149
+ </network-security-config>
150
+ ```
151
+
152
+ ```xml
153
+ <!-- AndroidManifest.xml -->
154
+ <application
155
+ android:networkSecurityConfig="@xml/network_security_config"
156
+ ... >
157
+ ```
158
+
159
+ ## Android Keystore (Runtime Key Storage)
160
+
161
+ For storing sensitive data at runtime (tokens, credentials), use Android Keystore — NOT JKS files:
162
+
163
+ ```kotlin
164
+ // EncryptedSharedPreferences (recommended for key-value storage)
165
+ val masterKey = MasterKey.Builder(context)
166
+ .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
167
+ .build()
168
+
169
+ val securePrefs = EncryptedSharedPreferences.create(
170
+ context, "secret_prefs", masterKey,
171
+ EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
172
+ EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
173
+ )
174
+ ```
175
+
176
+ ## Foreground Service Types (Android 14+)
177
+
178
+ Starting with Android 14 (API 34), every foreground service MUST declare a type:
179
+
180
+ ```xml
181
+ <service
182
+ android:name=".MyService"
183
+ android:foregroundServiceType="dataSync" />
184
+ ```
185
+
186
+ Valid types: `camera`, `connectedDevice`, `dataSync`, `health`, `location`, `mediaPlayback`, `microphone`, `phoneCall`, `shortService`, `specialUse`.
187
+
188
+ ## Permissions Policy
189
+
190
+ ```xml
191
+ <!-- Android 13+ notification permission -->
192
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
193
+
194
+ <!-- Android 13+ granular media permissions (replaces READ_EXTERNAL_STORAGE) -->
195
+ <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
196
+ <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
197
+
198
+ <!-- Use system photo picker instead of READ_MEDIA_IMAGES when possible -->
199
+ <!-- No permission needed: ActivityResultContracts.PickVisualMedia() -->
200
+ ```
201
+
202
+ ## Store Publishing Checklist
203
+
204
+ | Step | Description |
205
+ |------|-------------|
206
+ | 1. Register developer | Google Play ($25 one-time), Huawei (free), Xiaomi (free) |
207
+ | 2. Generate signed AAB | `./gradlew bundleRelease` |
208
+ | 3. Privacy policy | Required URL — must be accessible without login |
209
+ | 4. Data Safety section | Declare all data collection in Play Console (Mandatory) |
210
+ | 5. Data deletion | Apps with account creation MUST provide data deletion option |
211
+ | 6. App icon | 512x512 PNG |
212
+ | 7. Screenshots | Phone + tablet |
213
+ | 8. Description | App name, short description, full description |
214
+ | 9. Content rating | IARC rating questionnaire |
215
+ | 10. Target SDK | Must be API 35 (as of 2025/2026) |
216
+ | 11. Submit review | Google Play typically 1–3 days |
217
+
218
+ ## Build Optimization
219
+
220
+ ### ABI Splits (Reduce APK Size)
221
+
222
+ ```kotlin
223
+ // build.gradle.kts
224
+ android {
225
+ splits {
226
+ abi {
227
+ isEnable = true
228
+ reset()
229
+ include("arm64-v8a", "armeabi-v7a", "x86_64")
230
+ isUniversalApk = false
231
+ }
232
+ }
233
+ }
234
+ ```
235
+
236
+ ### R8 Code Shrinking
237
+
238
+ ```kotlin
239
+ // build.gradle.kts
240
+ android {
241
+ buildTypes {
242
+ release {
243
+ isMinifyEnabled = true
244
+ isShrinkResources = true
245
+ proguardFiles(
246
+ getDefaultProguardFile("proguard-android-optimize.txt"),
247
+ "proguard-rules.pro"
248
+ )
249
+ }
250
+ }
251
+ }
252
+ ```
253
+
254
+ ### Build Variant Management
255
+
256
+ ```kotlin
257
+ // build.gradle.kts
258
+ android {
259
+ flavorDimensions += "env"
260
+ productFlavors {
261
+ create("dev") {
262
+ dimension = "env"
263
+ applicationIdSuffix = ".dev"
264
+ versionNameSuffix = "-dev"
265
+ }
266
+ create("staging") {
267
+ dimension = "env"
268
+ applicationIdSuffix = ".staging"
269
+ }
270
+ create("prod") {
271
+ dimension = "env"
272
+ }
273
+ }
274
+ }
275
+ ```
276
+
277
+ ## CI/CD — GitHub Actions
278
+
279
+ ```yaml
280
+ name: Android Build
281
+ on:
282
+ push:
283
+ tags: ['v*']
284
+ jobs:
285
+ build:
286
+ runs-on: ubuntu-latest
287
+ steps:
288
+ - uses: actions/checkout@v4
289
+ - uses: actions/setup-java@v4
290
+ with:
291
+ distribution: 'temurin'
292
+ java-version: '17'
293
+ - name: Decode Keystore
294
+ run: echo "${{ secrets.RELEASE_KEYSTORE_BASE64 }}" | base64 --decode > app/release.jks
295
+ - name: Build AAB
296
+ env:
297
+ KEYSTORE_PATH: release.jks
298
+ KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
299
+ KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
300
+ KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
301
+ run: ./gradlew bundleRelease
302
+ - uses: actions/upload-artifact@v4
303
+ with:
304
+ name: aab
305
+ path: app/build/outputs/bundle/release/*.aab
306
+ ```
307
+
308
+ ## Common Pitfalls
309
+
310
+ | Issue | Fix |
311
+ |-------|-----|
312
+ | "Namespace not specified" | Add `namespace = "com.example.app"` in build.gradle (AGP 8.x requires it) |
313
+ | Signing error | Check environment variables; never hardcode passwords |
314
+ | ProGuard crash | Add `-keep` rules for models, native modules, serialization |
315
+ | Target SDK rejected | Google Play requires `targetSdk = 35` as of 2025 |
316
+ | 16KB alignment error | Add `pageAlignSharedLibs = true` in build.gradle |
317
+ | Foreground service crash | Declare `foregroundServiceType` in AndroidManifest (API 34+) |
318
+ | Data Safety rejection | Complete Data Safety section in Play Console |
319
+ | Privacy policy rejected | URL must be live, accessible without login, match Data Safety declaration |
320
+ | Cleartext traffic blocked | Android 9+ blocks HTTP by default; use HTTPS or configure network_security_config |
321
+ | `READ_EXTERNAL_STORAGE` not working | Android 13+ uses `READ_MEDIA_IMAGES`/`READ_MEDIA_VIDEO` instead |
322
+ | Play App Signing key lost | Upload key can be reset in Play Console; signing key is managed by Google |