android-sdd 1.0.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 (176) hide show
  1. package/dist/index.js +143 -0
  2. package/package.json +27 -0
  3. package/skills/Android Ecosystem/Baseline Profile Generator/SKILL.md +277 -0
  4. package/skills/Android Ecosystem/Glance/SKILL.md +315 -0
  5. package/skills/Android Platform/Configuration/SKILL.md +201 -0
  6. package/skills/Android Platform/Filesystem/SKILL.md +216 -0
  7. package/skills/Android Platform/Lifecycle/SKILL.md +233 -0
  8. package/skills/Android Platform/Manifest/SKILL.md +226 -0
  9. package/skills/Android Platform/Process Death Recovery/SKILL.md +214 -0
  10. package/skills/Android Platform/Resources/SKILL.md +234 -0
  11. package/skills/Android Platform/SavedStateHandle/SKILL.md +217 -0
  12. package/skills/Android Platform/State Restoration/SKILL.md +210 -0
  13. package/skills/Architecture/Bounded Context/SKILL.md +207 -0
  14. package/skills/Architecture/Clean Architecture/SKILL.md +229 -0
  15. package/skills/Architecture/Domain Modeling/SKILL.md +236 -0
  16. package/skills/Architecture/Entity Design/SKILL.md +243 -0
  17. package/skills/Architecture/Feature Isolation/SKILL.md +216 -0
  18. package/skills/Architecture/MVI/SKILL.md +224 -0
  19. package/skills/Architecture/MVVM/SKILL.md +198 -0
  20. package/skills/Architecture/Modularization/SKILL.md +194 -0
  21. package/skills/Architecture/Offline First/SKILL.md +249 -0
  22. package/skills/Architecture/Repository Pattern/SKILL.md +216 -0
  23. package/skills/Architecture/Side Effect Management/SKILL.md +278 -0
  24. package/skills/Architecture/State Management/SKILL.md +229 -0
  25. package/skills/Architecture/Unidirectional Data Flow/SKILL.md +196 -0
  26. package/skills/Architecture/Use Case Design/SKILL.md +244 -0
  27. package/skills/Architecture/Value Object/SKILL.md +226 -0
  28. package/skills/Build Infrastructure/Build Orchestration/SKILL.md +257 -0
  29. package/skills/Build Infrastructure/Dependency Compatibility Resolver/SKILL.md +259 -0
  30. package/skills/Build Infrastructure/Environment Validator/SKILL.md +311 -0
  31. package/skills/Build System/Build Cache/SKILL.md +233 -0
  32. package/skills/Build System/Build Flavor Strategy/SKILL.md +171 -0
  33. package/skills/Build System/Build Variant/SKILL.md +215 -0
  34. package/skills/Build System/Convention Plugin/SKILL.md +288 -0
  35. package/skills/Build System/Dependency Management/SKILL.md +261 -0
  36. package/skills/Build System/Gradle/SKILL.md +284 -0
  37. package/skills/Build System/Incremental Build/SKILL.md +199 -0
  38. package/skills/Build System/KAPT/SKILL.md +198 -0
  39. package/skills/Build System/KSP/SKILL.md +263 -0
  40. package/skills/Build System/Module Dependency Graph Validation/SKILL.md +223 -0
  41. package/skills/Build System/Specialized/C++/SKILL.md +308 -0
  42. package/skills/Build System/Specialized/JNI/SKILL.md +306 -0
  43. package/skills/Build System/Specialized/NDK/SKILL.md +264 -0
  44. package/skills/Build System/Version Catalog/SKILL.md +304 -0
  45. package/skills/Concurrency/Background Processing/SKILL.md +185 -0
  46. package/skills/Concurrency/Channel/SKILL.md +207 -0
  47. package/skills/Concurrency/Coroutine/SKILL.md +200 -0
  48. package/skills/Concurrency/Flow/SKILL.md +179 -0
  49. package/skills/Concurrency/Mutex Strategy/SKILL.md +185 -0
  50. package/skills/Concurrency/SharedFlow/SKILL.md +171 -0
  51. package/skills/Concurrency/StateFlow/SKILL.md +175 -0
  52. package/skills/Concurrency/Structured Concurrency/SKILL.md +197 -0
  53. package/skills/Concurrency/Synchronization Policy/SKILL.md +192 -0
  54. package/skills/Core Language/Annotation Processing/SKILL.md +224 -0
  55. package/skills/Core Language/DSL/SKILL.md +186 -0
  56. package/skills/Core Language/Extension Functions Design/SKILL.md +191 -0
  57. package/skills/Core Language/Immutability/SKILL.md +156 -0
  58. package/skills/Core Language/KMP/SKILL.md +182 -0
  59. package/skills/Core Language/Kotlin/SKILL.md +187 -0
  60. package/skills/Core Language/Reactive State Management/SKILL.md +228 -0
  61. package/skills/Core Language/Reactive Streams/SKILL.md +235 -0
  62. package/skills/Core Language/Serialization/SKILL.md +191 -0
  63. package/skills/Data Layer/Cache Strategy/SKILL.md +261 -0
  64. package/skills/Data Layer/Conflict Resolution/SKILL.md +248 -0
  65. package/skills/Data Layer/DAO/SKILL.md +225 -0
  66. package/skills/Data Layer/DTO Mapping/SKILL.md +269 -0
  67. package/skills/Data Layer/DataStore/SKILL.md +264 -0
  68. package/skills/Data Layer/Database Versioning Strategy/SKILL.md +215 -0
  69. package/skills/Data Layer/Encrypted Database/SKILL.md +212 -0
  70. package/skills/Data Layer/File Storage/SKILL.md +247 -0
  71. package/skills/Data Layer/Indexing/SKILL.md +184 -0
  72. package/skills/Data Layer/Key-Value Store Strategy/SKILL.md +185 -0
  73. package/skills/Data Layer/Merge Strategy/SKILL.md +240 -0
  74. package/skills/Data Layer/Migration/SKILL.md +243 -0
  75. package/skills/Data Layer/Paging/SKILL.md +264 -0
  76. package/skills/Data Layer/Proto DataStore/SKILL.md +250 -0
  77. package/skills/Data Layer/Room/SKILL.md +244 -0
  78. package/skills/Data Layer/SQLite/SKILL.md +255 -0
  79. package/skills/Data Layer/Sync Engine/SKILL.md +268 -0
  80. package/skills/Dependency Injection/Dagger/SKILL.md +283 -0
  81. package/skills/Dependency Injection/Hilt/SKILL.md +345 -0
  82. package/skills/Dependency Injection/Koin/SKILL.md +282 -0
  83. package/skills/Developer Experience/Detekt/SKILL.md +272 -0
  84. package/skills/Developer Experience/Lint Rule/SKILL.md +281 -0
  85. package/skills/Google Ecosystem/Analytics/SKILL.md +281 -0
  86. package/skills/Google Ecosystem/Crashlytics/SKILL.md +234 -0
  87. package/skills/Google Ecosystem/Firebase/SKILL.md +200 -0
  88. package/skills/Google Ecosystem/Firebase Messaging/SKILL.md +266 -0
  89. package/skills/Media/Audio/SKILL.md +257 -0
  90. package/skills/Media/Camera/SKILL.md +229 -0
  91. package/skills/Media/CameraX/SKILL.md +295 -0
  92. package/skills/Media/ExoPlayer/SKILL.md +258 -0
  93. package/skills/Media/Video/SKILL.md +228 -0
  94. package/skills/Meta Skills/Domain Error Model/SKILL.md +238 -0
  95. package/skills/Meta Skills/Error Handling/SKILL.md +255 -0
  96. package/skills/Meta Skills/Error Mapping/SKILL.md +232 -0
  97. package/skills/Meta Skills/Failure Strategy/SKILL.md +294 -0
  98. package/skills/Meta Skills/Migration Strategy/SKILL.md +305 -0
  99. package/skills/Meta Skills/User Friendly Errors/SKILL.md +334 -0
  100. package/skills/Navigation/Deep Navigation/SKILL.md +209 -0
  101. package/skills/Navigation/Navigation/SKILL.md +215 -0
  102. package/skills/Navigation/Nested Navigation/SKILL.md +214 -0
  103. package/skills/Networking/API Contract/SKILL.md +220 -0
  104. package/skills/Networking/Authentication/SKILL.md +210 -0
  105. package/skills/Networking/Certificate Pinning/SKILL.md +167 -0
  106. package/skills/Networking/Fallback Strategy/SKILL.md +182 -0
  107. package/skills/Networking/Ktor/SKILL.md +219 -0
  108. package/skills/Networking/Multipart Upload/SKILL.md +213 -0
  109. package/skills/Networking/OkHttp/SKILL.md +193 -0
  110. package/skills/Networking/REST/SKILL.md +178 -0
  111. package/skills/Networking/Rate Limiting/SKILL.md +170 -0
  112. package/skills/Networking/Retrofit/SKILL.md +241 -0
  113. package/skills/Networking/Retry-Backoff/SKILL.md +181 -0
  114. package/skills/Networking/Server-Sent Events (SSE)/SKILL.md +196 -0
  115. package/skills/Networking/WebSocket/SKILL.md +224 -0
  116. package/skills/Observability/Crash Reporting/SKILL.md +219 -0
  117. package/skills/Observability/Logging/SKILL.md +168 -0
  118. package/skills/Observability/Metrics/SKILL.md +227 -0
  119. package/skills/Observability/Structured Logging/SKILL.md +234 -0
  120. package/skills/Performance/ANR Prevention/SKILL.md +192 -0
  121. package/skills/Performance/Allocation Optimization/SKILL.md +179 -0
  122. package/skills/Performance/App Startup/SKILL.md +183 -0
  123. package/skills/Performance/Baseline Profile/SKILL.md +205 -0
  124. package/skills/Performance/Battery Optimization/SKILL.md +192 -0
  125. package/skills/Performance/Benchmark/SKILL.md +182 -0
  126. package/skills/Performance/Bitmap Optimization/SKILL.md +178 -0
  127. package/skills/Performance/Compose Optimization/SKILL.md +187 -0
  128. package/skills/Performance/Heap Management/SKILL.md +184 -0
  129. package/skills/Performance/Macrobenchmark/SKILL.md +214 -0
  130. package/skills/Performance/Memory Leak Prevention/SKILL.md +218 -0
  131. package/skills/Performance/Rendering Performance/SKILL.md +205 -0
  132. package/skills/Performance/Startup Optimization/SKILL.md +219 -0
  133. package/skills/Security/Biometric/SKILL.md +224 -0
  134. package/skills/Security/Certificate Transparency/SKILL.md +158 -0
  135. package/skills/Security/Cryptography/SKILL.md +244 -0
  136. package/skills/Security/Encrypted Storage/SKILL.md +273 -0
  137. package/skills/Security/Frida Detection/SKILL.md +230 -0
  138. package/skills/Security/Hook Detection/SKILL.md +197 -0
  139. package/skills/Security/Keystore/SKILL.md +272 -0
  140. package/skills/Security/Network Security Config/SKILL.md +186 -0
  141. package/skills/Security/Obfuscation/SKILL.md +226 -0
  142. package/skills/Security/Proguard/SKILL.md +202 -0
  143. package/skills/Security/R8/SKILL.md +234 -0
  144. package/skills/Security/Reverse Engineering Resistance/SKILL.md +267 -0
  145. package/skills/Security/Root Detection/SKILL.md +220 -0
  146. package/skills/Security/Secure Networking/SKILL.md +220 -0
  147. package/skills/System Integration/AlarmManager/SKILL.md +182 -0
  148. package/skills/System Integration/App Widget/SKILL.md +182 -0
  149. package/skills/System Integration/Deep Link/SKILL.md +187 -0
  150. package/skills/System Integration/Foreground Service/SKILL.md +212 -0
  151. package/skills/System Integration/Notification/SKILL.md +237 -0
  152. package/skills/System Integration/WorkManager/SKILL.md +256 -0
  153. package/skills/System Integration/clipboard/SKILL.md +155 -0
  154. package/skills/System Integration/share-intent/SKILL.md +182 -0
  155. package/skills/Testing/Compose Testing/SKILL.md +296 -0
  156. package/skills/Testing/Espresso/SKILL.md +292 -0
  157. package/skills/Testing/Fake Data/SKILL.md +245 -0
  158. package/skills/Testing/Integration Testing/SKILL.md +288 -0
  159. package/skills/Testing/Mocking/SKILL.md +229 -0
  160. package/skills/Testing/Snapshot Testing/SKILL.md +259 -0
  161. package/skills/Testing/UI Testing/SKILL.md +293 -0
  162. package/skills/Testing/Unit Testing/SKILL.md +309 -0
  163. package/skills/UI System/Bottom Sheet Patterns/SKILL.md +279 -0
  164. package/skills/UI System/Compose/SKILL.md +296 -0
  165. package/skills/UI System/Compose Animation/SKILL.md +281 -0
  166. package/skills/UI System/Compose Multiplatform/SKILL.md +261 -0
  167. package/skills/UI System/Compose Navigation/SKILL.md +255 -0
  168. package/skills/UI System/Compose Performance/SKILL.md +274 -0
  169. package/skills/UI System/Design System/SKILL.md +217 -0
  170. package/skills/UI System/Empty State Strategy/SKILL.md +208 -0
  171. package/skills/UI System/Keyboard Navigation/SKILL.md +214 -0
  172. package/skills/UI System/Loading Strategy/SKILL.md +254 -0
  173. package/skills/UI System/Material 3/SKILL.md +279 -0
  174. package/skills/UI System/RTL/SKILL.md +179 -0
  175. package/src/index.ts +182 -0
  176. package/tsconfig.json +19 -0
package/dist/index.js ADDED
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || function (mod) {
20
+ if (mod && mod.__esModule) return mod;
21
+ var result = {};
22
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
23
+ __setModuleDefault(result, mod);
24
+ return result;
25
+ };
26
+ var __importDefault = (this && this.__importDefault) || function (mod) {
27
+ return (mod && mod.__esModule) ? mod : { "default": mod };
28
+ };
29
+ Object.defineProperty(exports, "__esModule", { value: true });
30
+ const fs_1 = __importDefault(require("fs"));
31
+ const path_1 = __importDefault(require("path"));
32
+ const inquirer = require("inquirer");
33
+ /**
34
+ * GitHub Remote Skills Repo (ZIP)
35
+ */
36
+ const REMOTE_SKILLS_ZIP = "https://github.com/mozhdehnoury-byte/android-agent-skills/archive/refs/heads/main.zip";
37
+ /**
38
+ * ورود برنامه
39
+ */
40
+ async function main() {
41
+ const args = process.argv.slice(2);
42
+ const command = args[0];
43
+ if (command === "init") {
44
+ await initRemote();
45
+ return;
46
+ }
47
+ if (command === "install") {
48
+ const selectedSkills = await wizard(skillsPath());
49
+ await install(selectedSkills, skillsPath());
50
+ return;
51
+ }
52
+ await wizard(skillsPath());
53
+ }
54
+ /**
55
+ * مسیر skills (local fallback)
56
+ */
57
+ function skillsPath() {
58
+ return path_1.default.join(__dirname, "../skills");
59
+ }
60
+ /**
61
+ * wizard: انتخاب skill ها
62
+ */
63
+ async function wizard(basePath) {
64
+ const selectedSkills = {};
65
+ const parentFolders = fs_1.default.readdirSync(basePath);
66
+ for (const parent of parentFolders) {
67
+ const children = fs_1.default.readdirSync(path_1.default.join(basePath, parent));
68
+ const answer = await inquirer.prompt([
69
+ {
70
+ type: "checkbox",
71
+ name: "selected",
72
+ message: `Select ${parent} skills`,
73
+ choices: children
74
+ }
75
+ ]);
76
+ selectedSkills[parent] = answer.selected;
77
+ }
78
+ console.log("Selected Skills:");
79
+ console.log(selectedSkills);
80
+ return selectedSkills;
81
+ }
82
+ /**
83
+ * install: ساخت .agent + کپی skill ها + ساخت config
84
+ */
85
+ async function install(selectedSkills, basePath) {
86
+ console.log("🚀 Installing Android SDD skills...");
87
+ const agentRoot = path_1.default.join(process.cwd(), ".agent");
88
+ fs_1.default.mkdirSync(agentRoot, { recursive: true });
89
+ for (const [parent, skills] of Object.entries(selectedSkills)) {
90
+ for (const skill of skills) {
91
+ const source = path_1.default.join(basePath, parent, skill, "SKILL.md");
92
+ const targetDir = path_1.default.join(agentRoot, parent, skill);
93
+ fs_1.default.mkdirSync(targetDir, { recursive: true });
94
+ fs_1.default.copyFileSync(source, path_1.default.join(targetDir, "SKILL.md"));
95
+ console.log(`Installed: ${parent}/${skill}`);
96
+ }
97
+ }
98
+ const config = {
99
+ version: "1.0.0",
100
+ installedAt: new Date().toISOString(),
101
+ skills: selectedSkills
102
+ };
103
+ fs_1.default.writeFileSync(path_1.default.join(agentRoot, "config.json"), JSON.stringify(config, null, 2));
104
+ console.log("\n🎉 Done! Skills installed in .agent/");
105
+ }
106
+ /**
107
+ * Remote init (GitHub ZIP → auto-detect folder → wizard)
108
+ */
109
+ async function initRemote() {
110
+ console.log("🌍 Downloading skills from GitHub...");
111
+ const fetch = (await Promise.resolve().then(() => __importStar(require("node-fetch")))).default;
112
+ const unzipper = await Promise.resolve().then(() => __importStar(require("unzipper")));
113
+ const res = await fetch(REMOTE_SKILLS_ZIP);
114
+ const buffer = Buffer.from(await res.arrayBuffer());
115
+ const zipPath = path_1.default.join(process.cwd(), "skills.zip");
116
+ fs_1.default.writeFileSync(zipPath, buffer);
117
+ console.log("📦 Extracting skills...");
118
+ await fs_1.default.createReadStream(zipPath)
119
+ .pipe(unzipper.Extract({ path: process.cwd() }))
120
+ .promise();
121
+ /**
122
+ * 🔥 AUTO DETECT extracted skills path
123
+ * چون GitHub همیشه یک wrapper folder می‌سازه
124
+ */
125
+ const extractedBase = process.cwd();
126
+ const possiblePaths = [
127
+ path_1.default.join(extractedBase, "android-agent-skills-main"),
128
+ ];
129
+ let extractedPath = null;
130
+ for (const p of possiblePaths) {
131
+ if (fs_1.default.existsSync(p)) {
132
+ extractedPath = p;
133
+ break;
134
+ }
135
+ }
136
+ if (!extractedPath) {
137
+ throw new Error("❌ Could not find skills folder after extraction");
138
+ }
139
+ console.log("🧠 Running wizard...");
140
+ const selectedSkills = await wizard(extractedPath);
141
+ await install(selectedSkills, extractedPath);
142
+ }
143
+ main();
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "android-sdd",
3
+ "version": "1.0.0",
4
+ "description": "Android SDD CLI for managing skills",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "android-sdd": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "start": "ts-node src/index.ts"
12
+ },
13
+ "keywords": [],
14
+ "author": "",
15
+ "license": "ISC",
16
+ "type": "commonjs",
17
+ "devDependencies": {
18
+ "@types/inquirer": "^9.0.10",
19
+ "@types/node": "^25.9.3",
20
+ "typescript": "^5.3.3"
21
+ },
22
+ "dependencies": {
23
+ "inquirer": "^8.2.7",
24
+ "node-fetch": "^3.3.2",
25
+ "unzipper": "^0.12.3"
26
+ }
27
+ }
@@ -0,0 +1,277 @@
1
+ ---
2
+ name: baseline-profile-generator
3
+ description: >
4
+ Generating Baseline Profiles for Android app startup and runtime optimization.
5
+ Load this skill when setting up Baseline Profile generation, writing profile
6
+ rules, integrating with CI, or measuring startup improvement.
7
+ ---
8
+
9
+ # Baseline Profile Generator
10
+
11
+ ## Overview
12
+ Baseline Profiles pre-compile critical code paths (startup, common user journeys) so the Android Runtime (ART) doesn't need to JIT-compile them at runtime. This reduces app startup time and improves runtime performance — typically 20-40% faster startup on first launch after install.
13
+
14
+ ---
15
+
16
+ ## Core Principles
17
+
18
+ - Baseline Profiles target **critical user journeys** — not the entire app
19
+ - Profiles are included in the **release APK/AAB** — they ship to users
20
+ - Profile generation requires a **physical device or emulator** running the app
21
+ - Regenerate profiles when **critical code paths change** significantly
22
+ - Measure startup **before and after** to verify improvement
23
+
24
+ ---
25
+
26
+ ## Setup
27
+
28
+ ```toml
29
+ [versions]
30
+ androidx-benchmark = "1.3.1"
31
+ androidx-profileinstaller = "1.3.1"
32
+
33
+ [libraries]
34
+ androidx-benchmark-macro = { module = "androidx.benchmark:benchmark-macro-junit4", version.ref = "androidx-benchmark" }
35
+ androidx-profileinstaller = { module = "androidx.profileinstaller:profileinstaller", version.ref = "androidx-profileinstaller" }
36
+ androidx-test-uiautomator = { module = "androidx.test.uiautomator:uiautomator", version = "2.3.0" }
37
+
38
+ [plugins]
39
+ androidx-baselineprofile = { id = "androidx.baselineprofile", version.ref = "androidx-benchmark" }
40
+ ```
41
+
42
+ ```kotlin
43
+ // settings.gradle.kts
44
+ include(":baselineprofile")
45
+
46
+ // baselineprofile/build.gradle.kts
47
+ plugins {
48
+ alias(libs.plugins.android.test)
49
+ alias(libs.plugins.androidx.baselineprofile)
50
+ }
51
+
52
+ android {
53
+ namespace = "com.example.baselineprofile"
54
+ targetProjectPath = ":app"
55
+
56
+ defaultConfig {
57
+ minSdk = 28 // Baseline Profiles require API 28+
58
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
59
+ }
60
+ }
61
+
62
+ dependencies {
63
+ implementation(libs.androidx.test.uiautomator)
64
+ implementation(libs.androidx.benchmark.macro)
65
+ }
66
+
67
+ // app/build.gradle.kts
68
+ plugins {
69
+ alias(libs.plugins.androidx.baselineprofile)
70
+ }
71
+
72
+ dependencies {
73
+ implementation(libs.androidx.profileinstaller)
74
+ baselineProfile(project(":baselineprofile"))
75
+ }
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Writing Profile Rules
81
+
82
+ ```kotlin
83
+ // baselineprofile/src/main/kotlin/com/example/baselineprofile/BaselineProfileGenerator.kt
84
+
85
+ @RunWith(AndroidJUnit4::class)
86
+ class BaselineProfileGenerator {
87
+
88
+ @get:Rule
89
+ val rule = BaselineProfileRule()
90
+
91
+ @Test
92
+ fun generate() = rule.collect(
93
+ packageName = "com.example.app",
94
+ profileBlock = {
95
+ // ✅ Journey 1: App startup
96
+ startActivityAndWait()
97
+
98
+ // ✅ Journey 2: Navigate to main screen
99
+ device.findObject(By.text("Home")).click()
100
+ device.waitForIdle()
101
+
102
+ // ✅ Journey 3: Open a list and scroll
103
+ device.findObject(By.text("Users")).click()
104
+ device.waitForIdle()
105
+
106
+ device.findObject(By.res("user_list")).also { list ->
107
+ list.setGestureMargin(device.displayWidth / 5)
108
+ list.fling(Direction.DOWN)
109
+ device.waitForIdle()
110
+ list.fling(Direction.UP)
111
+ device.waitForIdle()
112
+ }
113
+
114
+ // ✅ Journey 4: Open detail screen
115
+ device.findObject(By.text("Ali Rezaei")).click()
116
+ device.waitForIdle()
117
+ }
118
+ )
119
+ }
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Generating the Profile
125
+
126
+ ```bash
127
+ # ✅ Generate profile — runs on connected device/emulator
128
+ ./gradlew :baselineprofile:generateBaselineProfile
129
+
130
+ # ✅ Generated file location
131
+ # app/src/main/baseline-prof.txt
132
+
133
+ # ✅ Verify file was generated
134
+ cat app/src/main/baseline-prof.txt
135
+ # Should contain lines like:
136
+ # HSPLcom/example/app/MainActivity;->onCreate(...)V
137
+ # Lcom/example/app/ui/UserListScreen;
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Generated Profile Format
143
+
144
+ ```
145
+ # baseline-prof.txt — auto-generated, commit to version control
146
+ HSPLcom/example/app/MainActivity;->onCreate(Landroid/os/Bundle;)V
147
+ HSPLcom/example/app/MainActivity;->onResume()V
148
+ Lcom/example/app/ui/UserListScreen;
149
+ Lcom/example/app/data/UserRepository;
150
+ PLcom/example/app/ui/UserCard;->invoke(Landroidx/compose/runtime/Composer;I)V
151
+
152
+ # H = Hot (compiled with full optimizations)
153
+ # S = Startup (compiled for startup path)
154
+ # P = Post-startup (compiled after startup)
155
+ # L = class loaded at startup
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Measuring Startup Improvement
161
+
162
+ ```kotlin
163
+ // ✅ Macrobenchmark test to measure startup time
164
+ @RunWith(AndroidJUnit4::class)
165
+ class StartupBenchmark {
166
+
167
+ @get:Rule
168
+ val benchmarkRule = MacrobenchmarkRule()
169
+
170
+ @Test
171
+ fun startupCompilationNone() = benchmarkRule.measureRepeated(
172
+ packageName = "com.example.app",
173
+ metrics = listOf(StartupTimingMetric()),
174
+ compilationMode = CompilationMode.None(), // no pre-compilation
175
+ startupMode = StartupMode.COLD,
176
+ iterations = 5,
177
+ measureBlock = { startActivityAndWait() }
178
+ )
179
+
180
+ @Test
181
+ fun startupWithBaselineProfile() = benchmarkRule.measureRepeated(
182
+ packageName = "com.example.app",
183
+ metrics = listOf(StartupTimingMetric()),
184
+ compilationMode = CompilationMode.Partial(
185
+ baselineProfileMode = BaselineProfileMode.Require
186
+ ),
187
+ startupMode = StartupMode.COLD,
188
+ iterations = 5,
189
+ measureBlock = { startActivityAndWait() }
190
+ )
191
+ }
192
+ ```
193
+
194
+ ---
195
+
196
+ ## ProfileInstaller
197
+
198
+ ```kotlin
199
+ // ✅ ProfileInstaller installs the profile at app install time
200
+ // No code needed — adding the dependency is sufficient
201
+ dependencies {
202
+ implementation(libs.androidx.profileinstaller)
203
+ }
204
+
205
+ // ✅ Force install profile for testing (debug builds)
206
+ class MainActivity : ComponentActivity() {
207
+ override fun onCreate(savedInstanceState: Bundle?) {
208
+ super.onCreate(savedInstanceState)
209
+ if (BuildConfig.DEBUG) {
210
+ ProfileVerifier.getCompilationStatusAsync()
211
+ .addListener({
212
+ val status = ProfileVerifier.getCompilationStatusAsync().get()
213
+ Log.d("Profile", "Status: ${status.profileInstallResultCode}")
214
+ }, ContextCompat.getMainExecutor(this))
215
+ }
216
+ }
217
+ }
218
+ ```
219
+
220
+ ---
221
+
222
+ ## CI Integration
223
+
224
+ ```yaml
225
+ # .github/workflows/generate-baseline-profile.yml
226
+ name: Generate Baseline Profile
227
+
228
+ on:
229
+ workflow_dispatch: # manual trigger
230
+ schedule:
231
+ - cron: '0 0 * * 1' # weekly on Monday
232
+
233
+ jobs:
234
+ generate-profile:
235
+ runs-on: macos-latest # macOS for Android emulator acceleration
236
+ steps:
237
+ - uses: actions/checkout@v4
238
+
239
+ - name: Enable KVM
240
+ run: |
241
+ echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
242
+ sudo udevadm control --reload-rules
243
+ sudo udevadm trigger --name-match=kvm
244
+
245
+ - uses: reactivecircus/android-emulator-runner@v2
246
+ with:
247
+ api-level: 34
248
+ target: google_apis
249
+ arch: x86_64
250
+ script: ./gradlew :baselineprofile:generateBaselineProfile
251
+
252
+ - name: Commit generated profile
253
+ run: |
254
+ git config user.email "ci@example.com"
255
+ git config user.name "CI Bot"
256
+ git add app/src/main/baseline-prof.txt
257
+ git commit -m "Update Baseline Profile" || echo "No changes to commit"
258
+ git push
259
+ ```
260
+
261
+ ---
262
+
263
+ ## Anti-Patterns
264
+
265
+ - Not committing `baseline-prof.txt` to version control — profile lost between builds
266
+ - Covering only app startup — also profile common user journeys (lists, navigation)
267
+ - Never regenerating the profile — drifts from actual hot paths over time
268
+ - Using emulator without Google Play — profile generation requires Play services
269
+ - Not measuring startup improvement — can't verify benefit
270
+
271
+ ---
272
+
273
+ ## Related Skills
274
+ - `baseline-profile` — applying and using Baseline Profiles
275
+ - `benchmark` — measuring performance with Macrobenchmark
276
+ - `startup-optimization` — app startup performance
277
+ - `compose-performance` — Compose-specific optimization