androjack-mcp 1.3.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.
- package/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +34 -0
- package/.github/pull_request_template.md +16 -0
- package/CONTRIBUTING.md +27 -0
- package/LICENSE +21 -0
- package/README.md +592 -0
- package/SECURITY.md +26 -0
- package/assets/AndroJack banner.png +0 -0
- package/assets/killer_argument.png +0 -0
- package/build/constants.js +412 -0
- package/build/http-server.js +163 -0
- package/build/http.js +151 -0
- package/build/index.js +553 -0
- package/build/install.js +379 -0
- package/build/logger.js +57 -0
- package/build/tools/api-level.js +170 -0
- package/build/tools/api36-compliance.js +282 -0
- package/build/tools/architecture.js +75 -0
- package/build/tools/build-publish.js +362 -0
- package/build/tools/component.js +90 -0
- package/build/tools/debugger.js +82 -0
- package/build/tools/gradle.js +234 -0
- package/build/tools/kmp.js +348 -0
- package/build/tools/kotlin-patterns.js +500 -0
- package/build/tools/large-screen.js +366 -0
- package/build/tools/m3-expressive.js +447 -0
- package/build/tools/navigation3.js +331 -0
- package/build/tools/ondevice-ai.js +283 -0
- package/build/tools/permissions.js +404 -0
- package/build/tools/play-policy.js +221 -0
- package/build/tools/scalability.js +621 -0
- package/build/tools/search.js +89 -0
- package/build/tools/testing.js +439 -0
- package/build/tools/wear.js +337 -0
- package/build/tools/xr.js +274 -0
- package/config/antigravity_mcp.json +32 -0
- package/config/claude_desktop_config.json +17 -0
- package/config/cursor_mcp.json +21 -0
- package/config/jetbrains_mcp.json +28 -0
- package/config/kiro_mcp.json +40 -0
- package/config/vscode_mcp.json +24 -0
- package/config/windsurf_mcp.json +18 -0
- package/package.json +51 -0
- package/src/constants.ts +436 -0
- package/src/http-server.ts +186 -0
- package/src/http.ts +190 -0
- package/src/index.ts +702 -0
- package/src/install.ts +441 -0
- package/src/logger.ts +67 -0
- package/src/tools/api-level.ts +198 -0
- package/src/tools/api36-compliance.ts +289 -0
- package/src/tools/architecture.ts +94 -0
- package/src/tools/build-publish.ts +379 -0
- package/src/tools/component.ts +106 -0
- package/src/tools/debugger.ts +111 -0
- package/src/tools/gradle.ts +288 -0
- package/src/tools/kmp.ts +352 -0
- package/src/tools/kotlin-patterns.ts +534 -0
- package/src/tools/large-screen.ts +391 -0
- package/src/tools/m3-expressive.ts +473 -0
- package/src/tools/navigation3.ts +338 -0
- package/src/tools/ondevice-ai.ts +287 -0
- package/src/tools/permissions.ts +445 -0
- package/src/tools/play-policy.ts +229 -0
- package/src/tools/scalability.ts +646 -0
- package/src/tools/search.ts +112 -0
- package/src/tools/testing.ts +460 -0
- package/src/tools/wear.ts +343 -0
- package/src/tools/xr.ts +278 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
// Tool 20: Wear OS Developer Guide
|
|
2
|
+
// Hundreds of millions of Wear OS devices. M3 Expressive for Wear went stable August 2025.
|
|
3
|
+
// Wear OS 5 (API 35) is current. AI tools generate phone Compose code that doesn't compile on Wear.
|
|
4
|
+
export async function androidWearOsGuide(topic) {
|
|
5
|
+
const t = topic.toLowerCase().trim();
|
|
6
|
+
const overview = `
|
|
7
|
+
# Wear OS Developer Guide — Official Reference
|
|
8
|
+
Source: https://developer.android.com/training/wearables
|
|
9
|
+
|
|
10
|
+
## Platform Status (2026)
|
|
11
|
+
|
|
12
|
+
| Component | Status |
|
|
13
|
+
|-----------|--------|
|
|
14
|
+
| Wear OS 5 (API 35) | Current |
|
|
15
|
+
| Jetpack Compose for Wear OS | Stable |
|
|
16
|
+
| Material 3 Expressive for Wear | Stable (August 2025) |
|
|
17
|
+
| Health Services API | Stable |
|
|
18
|
+
| Tiles API | Stable |
|
|
19
|
+
| Complications API | Stable |
|
|
20
|
+
|
|
21
|
+
## Why Phone Compose Code Fails on Wear OS
|
|
22
|
+
|
|
23
|
+
Wear OS uses a DIFFERENT set of Compose dependencies. If you add phone Compose to a Wear module:
|
|
24
|
+
- Different components (ScalingLazyColumn not LazyColumn, Chip not Button, etc.)
|
|
25
|
+
- Different scrolling behavior (curved/rotary input)
|
|
26
|
+
- Different navigation (SwipeDismissableNavHost)
|
|
27
|
+
- Different theming (WearMaterialTheme)
|
|
28
|
+
|
|
29
|
+
**AI tools generate phone Compose code. This does not compile on Wear OS.**
|
|
30
|
+
|
|
31
|
+
## Project Structure for Phone + Wear
|
|
32
|
+
|
|
33
|
+
\`\`\`
|
|
34
|
+
myapp/
|
|
35
|
+
app/ ← Phone module (regular Compose)
|
|
36
|
+
wearapp/ ← Wear module (Wear Compose)
|
|
37
|
+
shared/ ← Shared business logic (KMP or Android library)
|
|
38
|
+
\`\`\`
|
|
39
|
+
|
|
40
|
+
## Wear OS Dependencies (Different from Phone!)
|
|
41
|
+
|
|
42
|
+
\`\`\`toml
|
|
43
|
+
# libs.versions.toml
|
|
44
|
+
[versions]
|
|
45
|
+
wear-compose = "1.4.0"
|
|
46
|
+
wear-tiles = "1.4.0"
|
|
47
|
+
wear-watchface = "1.2.1"
|
|
48
|
+
health-services = "1.1.0"
|
|
49
|
+
horologist = "0.6.17" # Google's Wear utility library
|
|
50
|
+
|
|
51
|
+
[libraries]
|
|
52
|
+
# Wear Compose — NOT the same as phone Compose
|
|
53
|
+
wear-compose-foundation = { group = "androidx.wear.compose", name = "compose-foundation", version.ref = "wear-compose" }
|
|
54
|
+
wear-compose-material3 = { group = "androidx.wear.compose", name = "compose-material3", version.ref = "wear-compose" }
|
|
55
|
+
wear-compose-navigation = { group = "androidx.wear.compose", name = "compose-navigation", version.ref = "wear-compose" }
|
|
56
|
+
wear-compose-ui-tooling = { group = "androidx.wear.compose", name = "compose-ui-tooling", version.ref = "wear-compose" }
|
|
57
|
+
|
|
58
|
+
# Tiles
|
|
59
|
+
wear-tiles = { group = "androidx.wear.tiles", name = "tiles", version.ref = "wear-tiles" }
|
|
60
|
+
wear-tiles-material = { group = "androidx.wear.tiles", name = "tiles-material", version.ref = "wear-tiles" }
|
|
61
|
+
|
|
62
|
+
# Health Services
|
|
63
|
+
health-services = { group = "androidx.health", name = "health-services-client", version.ref = "health-services" }
|
|
64
|
+
|
|
65
|
+
# Horologist — Google's Wear utils (date/time pickers, rotary, audio)
|
|
66
|
+
horologist-compose-layout = { group = "com.google.android.horologist", name = "horologist-compose-layout", version.ref = "horologist" }
|
|
67
|
+
\`\`\`
|
|
68
|
+
|
|
69
|
+
Source: https://developer.android.com/training/wearables
|
|
70
|
+
`;
|
|
71
|
+
const compose = `
|
|
72
|
+
# Wear OS — Compose for Wear OS
|
|
73
|
+
Source: https://developer.android.com/training/wearables/compose
|
|
74
|
+
|
|
75
|
+
## Key Component Differences vs Phone Compose
|
|
76
|
+
|
|
77
|
+
| Phone Compose | Wear Compose Equivalent | Why Different |
|
|
78
|
+
|--------------|------------------------|---------------|
|
|
79
|
+
| LazyColumn | ScalingLazyColumn | Curved/cylindrical scrolling on round watches |
|
|
80
|
+
| Button | Chip / CompactChip | Optimized for small touch targets |
|
|
81
|
+
| Text | Text (same) | — |
|
|
82
|
+
| Icon | Icon (same) | — |
|
|
83
|
+
| Scaffold | TimeText + ScalingLazyColumn + PositionIndicator | Wear-specific chrome |
|
|
84
|
+
| NavHost | SwipeDismissableNavHost | Swipe-to-dismiss back gesture |
|
|
85
|
+
| AlertDialog | Alert | Wear-sized dialog |
|
|
86
|
+
| BottomSheetScaffold | (no equivalent) | Use scrolling content instead |
|
|
87
|
+
|
|
88
|
+
## Basic Wear OS Compose Screen
|
|
89
|
+
|
|
90
|
+
\`\`\`kotlin
|
|
91
|
+
@Composable
|
|
92
|
+
fun WearApp() {
|
|
93
|
+
WearMaterialTheme { // NOT MaterialTheme — use WearMaterialTheme
|
|
94
|
+
Scaffold(
|
|
95
|
+
timeText = { TimeText() }, // Clock in top arc — mandatory for all Wear screens
|
|
96
|
+
positionIndicator = {
|
|
97
|
+
PositionIndicator(scalingLazyListState = listState)
|
|
98
|
+
}
|
|
99
|
+
) {
|
|
100
|
+
ScalingLazyColumn( // NOT LazyColumn — curved scrolling for round screen
|
|
101
|
+
state = listState,
|
|
102
|
+
modifier = Modifier.fillMaxSize()
|
|
103
|
+
) {
|
|
104
|
+
item { Text("Hello Wear!") }
|
|
105
|
+
items(items) { item ->
|
|
106
|
+
Chip(
|
|
107
|
+
onClick = { /* ... */ },
|
|
108
|
+
label = { Text(item.title) },
|
|
109
|
+
icon = { Icon(Icons.Default.Star, contentDescription = null) }
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
\`\`\`
|
|
117
|
+
|
|
118
|
+
## Navigation on Wear OS
|
|
119
|
+
|
|
120
|
+
\`\`\`kotlin
|
|
121
|
+
// SwipeDismissableNavHost — user swipes from left to go back (NOT NavHost)
|
|
122
|
+
@Composable
|
|
123
|
+
fun WearNavigation() {
|
|
124
|
+
val navController = rememberSwipeDismissableNavController()
|
|
125
|
+
|
|
126
|
+
SwipeDismissableNavHost(
|
|
127
|
+
navController = navController,
|
|
128
|
+
startDestination = "home"
|
|
129
|
+
) {
|
|
130
|
+
composable("home") {
|
|
131
|
+
HomeScreen(onNavigateToDetail = { navController.navigate("detail/$it") })
|
|
132
|
+
}
|
|
133
|
+
composable("detail/{id}") { backStackEntry ->
|
|
134
|
+
val id = backStackEntry.arguments?.getString("id") ?: return@composable
|
|
135
|
+
DetailScreen(id = id)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
\`\`\`
|
|
140
|
+
|
|
141
|
+
## Rotary Input — The Watch Crown/Bezel
|
|
142
|
+
|
|
143
|
+
\`\`\`kotlin
|
|
144
|
+
// Handle rotary input (watch crown rotation) for scrolling
|
|
145
|
+
@Composable
|
|
146
|
+
fun RotaryScrollableList(items: List<String>) {
|
|
147
|
+
val listState = rememberScalingLazyListState()
|
|
148
|
+
val focusRequester = rememberActiveFocusRequester()
|
|
149
|
+
|
|
150
|
+
ScalingLazyColumn(
|
|
151
|
+
state = listState,
|
|
152
|
+
modifier = Modifier
|
|
153
|
+
.onRotaryScrollEvent { event ->
|
|
154
|
+
// event.verticalScrollPixels: positive = scroll down, negative = scroll up
|
|
155
|
+
true
|
|
156
|
+
}
|
|
157
|
+
.focusRequester(focusRequester)
|
|
158
|
+
.focusable(),
|
|
159
|
+
) {
|
|
160
|
+
items(items) { Text(it) }
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
\`\`\`
|
|
164
|
+
|
|
165
|
+
Source: https://developer.android.com/training/wearables/compose
|
|
166
|
+
`;
|
|
167
|
+
const tiles = `
|
|
168
|
+
# Wear OS — Tiles (Glanceable Information)
|
|
169
|
+
Source: https://developer.android.com/training/articles/wear-tiles
|
|
170
|
+
|
|
171
|
+
## What Tiles Are
|
|
172
|
+
|
|
173
|
+
Tiles are always-available, fast-loading surfaces that appear when users swipe
|
|
174
|
+
on the watch face. They show glanceable information without launching an app.
|
|
175
|
+
|
|
176
|
+
## Tiles vs App UI — When to Use Each
|
|
177
|
+
|
|
178
|
+
| Use Case | Tiles | App UI |
|
|
179
|
+
|----------|-------|--------|
|
|
180
|
+
| Current heart rate, steps | ✅ Tiles | — |
|
|
181
|
+
| Weather at a glance | ✅ Tiles | — |
|
|
182
|
+
| Quick action (start workout) | ✅ Tiles | — |
|
|
183
|
+
| Detailed workout history | — | ✅ App UI |
|
|
184
|
+
| Settings / preferences | — | ✅ App UI |
|
|
185
|
+
| Complex interactions | — | ✅ App UI |
|
|
186
|
+
|
|
187
|
+
## Tile Implementation
|
|
188
|
+
|
|
189
|
+
\`\`\`kotlin
|
|
190
|
+
class FitnessTileService : TileService() {
|
|
191
|
+
|
|
192
|
+
override fun onTileRequest(requestParams: RequestBuilders.TileRequest) =
|
|
193
|
+
Futures.immediateFuture(
|
|
194
|
+
TileBuilders.Tile.Builder()
|
|
195
|
+
.setResourcesVersion("1")
|
|
196
|
+
.setTileTimeline(
|
|
197
|
+
TimelineBuilders.Timeline.fromLayoutElement(
|
|
198
|
+
layoutElement(requestParams)
|
|
199
|
+
)
|
|
200
|
+
)
|
|
201
|
+
.build()
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
private fun layoutElement(params: RequestBuilders.TileRequest): LayoutElement {
|
|
205
|
+
val steps = getStepsCount() // Your data source
|
|
206
|
+
return PrimaryLayout.Builder(params.deviceConfiguration)
|
|
207
|
+
.setContent(
|
|
208
|
+
Text.Builder()
|
|
209
|
+
.setText(stringLayoutElement("$steps steps"))
|
|
210
|
+
.setTypography(Typography.TYPOGRAPHY_DISPLAY1)
|
|
211
|
+
.setColor(argb(0xFF4CAF50.toInt()))
|
|
212
|
+
.build()
|
|
213
|
+
)
|
|
214
|
+
.setPrimaryChipContent(
|
|
215
|
+
CompactChip.Builder(
|
|
216
|
+
this,
|
|
217
|
+
LaunchAction.Builder()
|
|
218
|
+
.setAndroidActivity(
|
|
219
|
+
AndroidActivity.Builder()
|
|
220
|
+
.setClassName(MainActivity::class.java.name)
|
|
221
|
+
.setPackageName(packageName)
|
|
222
|
+
.build()
|
|
223
|
+
)
|
|
224
|
+
.build(),
|
|
225
|
+
params.requestedTileId,
|
|
226
|
+
params.deviceConfiguration
|
|
227
|
+
)
|
|
228
|
+
.setIconContent(Icons.Activity)
|
|
229
|
+
.build()
|
|
230
|
+
)
|
|
231
|
+
.build()
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
override fun onResourcesRequest(requestParams: ResourceBuilders.ResourcesRequest) =
|
|
235
|
+
Futures.immediateFuture(ResourceBuilders.Resources.Builder().setVersion("1").build())
|
|
236
|
+
}
|
|
237
|
+
\`\`\`
|
|
238
|
+
|
|
239
|
+
\`\`\`xml
|
|
240
|
+
<!-- AndroidManifest.xml -->
|
|
241
|
+
<service android:name=".FitnessTileService"
|
|
242
|
+
android:exported="true"
|
|
243
|
+
android:permission="com.google.android.wearable.permission.BIND_TILE_PROVIDER">
|
|
244
|
+
<intent-filter>
|
|
245
|
+
<action android:name="androidx.wear.tiles.action.BIND_TILE_PROVIDER" />
|
|
246
|
+
</intent-filter>
|
|
247
|
+
<meta-data android:name="androidx.wear.tiles.PREVIEW"
|
|
248
|
+
android:resource="@drawable/tile_preview" />
|
|
249
|
+
</service>
|
|
250
|
+
\`\`\`
|
|
251
|
+
|
|
252
|
+
Source: https://developer.android.com/training/articles/wear-tiles
|
|
253
|
+
`;
|
|
254
|
+
const healthServices = `
|
|
255
|
+
# Wear OS — Health Services API
|
|
256
|
+
Source: https://developer.android.com/health-and-fitness/guides/health-services
|
|
257
|
+
|
|
258
|
+
## What Health Services Provides
|
|
259
|
+
|
|
260
|
+
Health Services is the official API for sensor data on Wear OS (heart rate, steps,
|
|
261
|
+
calories, SpO2, ECG on supported hardware). Use this instead of raw SensorManager.
|
|
262
|
+
|
|
263
|
+
## Exercise Session (Workout Tracking)
|
|
264
|
+
|
|
265
|
+
\`\`\`kotlin
|
|
266
|
+
// Permissions required in manifest
|
|
267
|
+
// <uses-permission android:name="android.permission.BODY_SENSORS" />
|
|
268
|
+
// <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
|
|
269
|
+
|
|
270
|
+
@HiltViewModel
|
|
271
|
+
class WorkoutViewModel @Inject constructor(
|
|
272
|
+
private val healthClient: ExerciseClient
|
|
273
|
+
) : ViewModel() {
|
|
274
|
+
|
|
275
|
+
private val _heartRate = MutableStateFlow(0)
|
|
276
|
+
val heartRate = _heartRate.asStateFlow()
|
|
277
|
+
|
|
278
|
+
fun startWorkout() {
|
|
279
|
+
viewModelScope.launch {
|
|
280
|
+
val config = ExerciseConfig(
|
|
281
|
+
exerciseType = ExerciseType.RUNNING,
|
|
282
|
+
dataTypes = setOf(DataType.HEART_RATE_BPM, DataType.STEPS, DataType.CALORIES_TOTAL),
|
|
283
|
+
isAutoPauseAndResumeEnabled = true
|
|
284
|
+
)
|
|
285
|
+
healthClient.startExercise(config)
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
fun observeHeartRate() {
|
|
290
|
+
viewModelScope.launch {
|
|
291
|
+
healthClient.getExerciseStateUpdates().collect { update ->
|
|
292
|
+
update.latestMetrics[DataType.HEART_RATE_BPM]?.let { samples ->
|
|
293
|
+
_heartRate.value = samples.last().value.toInt()
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
\`\`\`
|
|
300
|
+
|
|
301
|
+
## Passive Monitoring (Background Step Counting)
|
|
302
|
+
|
|
303
|
+
\`\`\`kotlin
|
|
304
|
+
// PassiveListenerService — runs in background without active exercise session
|
|
305
|
+
class StepCounterService : PassiveListenerService() {
|
|
306
|
+
override fun onNewDataPointsReceived(dataPoints: DataPointContainer) {
|
|
307
|
+
val steps = dataPoints.getData(DataType.STEPS).lastOrNull()?.value ?: return
|
|
308
|
+
// Update your data store with the new step count
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Register in manifest
|
|
313
|
+
// <service android:name=".StepCounterService"
|
|
314
|
+
// android:exported="true"
|
|
315
|
+
// android:permission="com.google.android.wearable.healthservices.permission.BIND_HEALTH_SERVICES_LISTENER">
|
|
316
|
+
// <intent-filter>
|
|
317
|
+
// <action android:name="androidx.health.services.PassiveListenerService" />
|
|
318
|
+
// </intent-filter>
|
|
319
|
+
// </service>
|
|
320
|
+
\`\`\`
|
|
321
|
+
|
|
322
|
+
Source: https://developer.android.com/health-and-fitness/guides/health-services
|
|
323
|
+
`;
|
|
324
|
+
if (t.includes("compose") || t.includes("ui") || t.includes("screen") || t.includes("chip") || t.includes("scaffold")) {
|
|
325
|
+
return compose;
|
|
326
|
+
}
|
|
327
|
+
if (t.includes("tile") || t.includes("glance"))
|
|
328
|
+
return tiles;
|
|
329
|
+
if (t.includes("health") || t.includes("heart") || t.includes("step") || t.includes("sensor") || t.includes("exercise")) {
|
|
330
|
+
return healthServices;
|
|
331
|
+
}
|
|
332
|
+
return overview + "\n\n---\n\n" +
|
|
333
|
+
"**Query topics:** 'compose' (ScalingLazyColumn, Chip, SwipeDismissableNavHost — NOT phone Compose), " +
|
|
334
|
+
"'tiles' (glanceable surfaces for watch face swipe), " +
|
|
335
|
+
"'health services' (heart rate, steps, exercise tracking)\n\n" +
|
|
336
|
+
"Source: https://developer.android.com/training/wearables";
|
|
337
|
+
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
// Tool 19: Android XR Guide
|
|
2
|
+
// Android XR SDK reached Developer Preview 3 in December 2025.
|
|
3
|
+
// Samsung Galaxy XR launched October 2025. 5+ devices expected in 2026.
|
|
4
|
+
// AI tools generate standard Compose code for XR — technically works but misses all spatial APIs.
|
|
5
|
+
export async function androidXrGuide(topic) {
|
|
6
|
+
const t = topic.toLowerCase().trim();
|
|
7
|
+
const overview = `
|
|
8
|
+
# Android XR — Official Developer Reference
|
|
9
|
+
Source: https://developer.android.com/xr
|
|
10
|
+
Source: https://developer.android.com/develop/ui/compose/xr
|
|
11
|
+
|
|
12
|
+
## Status (February 2026)
|
|
13
|
+
|
|
14
|
+
| Component | Status |
|
|
15
|
+
|-----------|--------|
|
|
16
|
+
| Android XR SDK | Developer Preview 3 (Dec 2025) |
|
|
17
|
+
| Jetpack Compose for XR | Developer Preview 3 |
|
|
18
|
+
| ARCore for XR | Developer Preview 3 |
|
|
19
|
+
| Samsung Galaxy XR | Launched October 2025 |
|
|
20
|
+
| Additional 2026 XR devices | Samsung AR glasses, XREAL, Warby Parker, Gentle Monster |
|
|
21
|
+
|
|
22
|
+
## What Android XR Is
|
|
23
|
+
|
|
24
|
+
Android XR is the platform for spatial computing on Android headsets and AR glasses.
|
|
25
|
+
It runs standard Android apps as 2D panels in a spatial environment, AND allows apps
|
|
26
|
+
to go "spatial" using new Compose for XR APIs.
|
|
27
|
+
|
|
28
|
+
Standard Compose apps work on XR headsets as 2D panels — no XR SDK required.
|
|
29
|
+
Add XR-specific APIs to give users spatial, immersive experiences.
|
|
30
|
+
|
|
31
|
+
## Key XR Concepts
|
|
32
|
+
|
|
33
|
+
| Concept | What It Is |
|
|
34
|
+
|---------|-----------|
|
|
35
|
+
| Subspace | The 3D environment where spatial content is placed |
|
|
36
|
+
| SpatialPanel | A flat 2D Compose surface positioned in 3D space |
|
|
37
|
+
| UserSubspace | Content that "follows" the user as they move |
|
|
38
|
+
| Orbiter | A floating UI element that orbits around a SpatialPanel |
|
|
39
|
+
| SceneCore | Low-level 3D scene graph API |
|
|
40
|
+
| SubspaceModifier | Sizing/positioning in the 3D environment (width/height as fraction of comfortable view) |
|
|
41
|
+
|
|
42
|
+
Source: https://developer.android.com/xr
|
|
43
|
+
`;
|
|
44
|
+
const setup = `
|
|
45
|
+
# Android XR — Setup & Dependencies
|
|
46
|
+
Source: https://developer.android.com/xr/get-started
|
|
47
|
+
|
|
48
|
+
## Dependencies
|
|
49
|
+
|
|
50
|
+
\`\`\`toml
|
|
51
|
+
# libs.versions.toml
|
|
52
|
+
[versions]
|
|
53
|
+
xr-compose = "1.0.0-alpha03" # Check developer.android.com/xr for latest
|
|
54
|
+
arcore-xr = "1.0.0-alpha03"
|
|
55
|
+
|
|
56
|
+
[libraries]
|
|
57
|
+
compose-xr = { group = "androidx.xr.compose", name = "compose", version.ref = "xr-compose" }
|
|
58
|
+
arcore-xr = { group = "com.google.ar", name = "core-xr", version.ref = "arcore-xr" }
|
|
59
|
+
|
|
60
|
+
[plugins]
|
|
61
|
+
# No special plugin needed — standard Android plugin works
|
|
62
|
+
\`\`\`
|
|
63
|
+
|
|
64
|
+
\`\`\`kotlin
|
|
65
|
+
// build.gradle.kts
|
|
66
|
+
implementation(libs.compose.xr)
|
|
67
|
+
|
|
68
|
+
// Optional — only if using ARCore features (face tracking, plane detection, etc.)
|
|
69
|
+
implementation(libs.arcore.xr)
|
|
70
|
+
\`\`\`
|
|
71
|
+
|
|
72
|
+
## Manifest — Declare XR Feature (Optional — Recommended)
|
|
73
|
+
|
|
74
|
+
\`\`\`xml
|
|
75
|
+
<!-- Optional — declare that your app supports XR but also runs on non-XR devices -->
|
|
76
|
+
<uses-feature
|
|
77
|
+
android:name="android.hardware.type.xr"
|
|
78
|
+
android:required="false" /> <!-- false = app still available on non-XR devices -->
|
|
79
|
+
\`\`\`
|
|
80
|
+
|
|
81
|
+
Source: https://developer.android.com/xr/get-started
|
|
82
|
+
`;
|
|
83
|
+
const spatialUi = `
|
|
84
|
+
# Android XR — Spatial UI with Compose for XR
|
|
85
|
+
Source: https://developer.android.com/develop/ui/compose/xr/spatial-ui
|
|
86
|
+
|
|
87
|
+
## SpatialPanel — A Compose UI in 3D Space
|
|
88
|
+
|
|
89
|
+
\`\`\`kotlin
|
|
90
|
+
@Composable
|
|
91
|
+
fun XrApp() {
|
|
92
|
+
// Check if running on XR device
|
|
93
|
+
val xrEnvironment = LocalXrEnvironment.current
|
|
94
|
+
|
|
95
|
+
if (xrEnvironment != null) {
|
|
96
|
+
// XR path — use spatial APIs
|
|
97
|
+
SpatialLayout {
|
|
98
|
+
SpatialPanel(
|
|
99
|
+
modifier = SubspaceModifier
|
|
100
|
+
.width(800.dp)
|
|
101
|
+
.height(600.dp)
|
|
102
|
+
.move(x = 0.dp, y = 0.dp, z = (-1.5).dp) // 1.5 meters in front of user
|
|
103
|
+
) {
|
|
104
|
+
// Regular Compose content inside the panel
|
|
105
|
+
AppMainContent()
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
// Non-XR path — regular Compose
|
|
110
|
+
AppMainContent()
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
\`\`\`
|
|
114
|
+
|
|
115
|
+
## UserSubspace — Content That Follows the User
|
|
116
|
+
|
|
117
|
+
\`\`\`kotlin
|
|
118
|
+
@Composable
|
|
119
|
+
fun FloatingNotification(message: String) {
|
|
120
|
+
// UserSubspace content "follows" the user as they look around
|
|
121
|
+
// Ideal for persistent UI like notifications, status indicators
|
|
122
|
+
UserSubspace {
|
|
123
|
+
SpatialPanel(
|
|
124
|
+
modifier = SubspaceModifier
|
|
125
|
+
.width(300.dp)
|
|
126
|
+
.height(100.dp)
|
|
127
|
+
.move(x = 200.dp, y = (-150).dp, z = (-1.0).dp) // Top-right of view
|
|
128
|
+
) {
|
|
129
|
+
NotificationCard(message = message)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
\`\`\`
|
|
134
|
+
|
|
135
|
+
## Orbiter — Floating Tool Panels
|
|
136
|
+
|
|
137
|
+
\`\`\`kotlin
|
|
138
|
+
@Composable
|
|
139
|
+
fun DocumentEditorXr() {
|
|
140
|
+
SpatialLayout {
|
|
141
|
+
// Main document panel
|
|
142
|
+
SpatialPanel(
|
|
143
|
+
modifier = SubspaceModifier.fillMaxWidth(0.7f).fillMaxHeight(0.8f)
|
|
144
|
+
) {
|
|
145
|
+
DocumentContent()
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Orbiter — formatting toolbar floating to the right of the main panel
|
|
149
|
+
Orbiter(
|
|
150
|
+
position = OrbiterEdge.End,
|
|
151
|
+
offset = 16.dp,
|
|
152
|
+
alignment = Alignment.CenterVertically
|
|
153
|
+
) {
|
|
154
|
+
FormattingToolbar()
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
\`\`\`
|
|
159
|
+
|
|
160
|
+
## Material Design for XR — Auto-Spatial Components
|
|
161
|
+
|
|
162
|
+
When using Material 3 with Compose for XR, some components automatically get spatial treatment:
|
|
163
|
+
- **TopAppBar** becomes an Orbiter floating above the panel
|
|
164
|
+
- **NavigationBar** becomes an Orbiter below or to the side of the panel
|
|
165
|
+
- **Dialogs** lift off the surface and appear as floating panels in front
|
|
166
|
+
|
|
167
|
+
No code changes needed if you're already using standard Material 3 components.
|
|
168
|
+
|
|
169
|
+
Source: https://developer.android.com/develop/ui/compose/xr/spatial-ui
|
|
170
|
+
`;
|
|
171
|
+
const arcore = `
|
|
172
|
+
# Android XR — ARCore for XR (Face Tracking, Plane Detection)
|
|
173
|
+
Source: https://developers.google.com/ar/develop/android-xr
|
|
174
|
+
|
|
175
|
+
## ARCore for XR Capabilities
|
|
176
|
+
|
|
177
|
+
ARCore for XR adds:
|
|
178
|
+
- **Face Tracking** — 68 facial blendshape values (ARCore XR face mesh)
|
|
179
|
+
- **Hand Tracking** — finger joint positions for gesture recognition
|
|
180
|
+
- **Plane Detection** — horizontal/vertical surfaces in the physical world
|
|
181
|
+
- **Depth API** — depth map for occlusion with real-world objects
|
|
182
|
+
|
|
183
|
+
## Face Tracking Setup
|
|
184
|
+
|
|
185
|
+
\`\`\`kotlin
|
|
186
|
+
// Requires android.permission.CAMERA in manifest
|
|
187
|
+
|
|
188
|
+
class FaceTrackingActivity : ComponentActivity() {
|
|
189
|
+
private lateinit var session: Session
|
|
190
|
+
|
|
191
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
192
|
+
super.onCreate(savedInstanceState)
|
|
193
|
+
|
|
194
|
+
// Check ARCore XR availability
|
|
195
|
+
if (!ArCoreApk.getInstance().isXrAvailable(this)) return
|
|
196
|
+
|
|
197
|
+
session = Session(this, EnumSet.of(Session.Feature.FRONT_CAMERA))
|
|
198
|
+
session.configure(
|
|
199
|
+
session.config.apply {
|
|
200
|
+
faceDetectorMode = Config.FaceDetectorMode.ENABLED
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// In render loop — read 68 blendshape coefficients per face
|
|
206
|
+
fun processFaceFrame(frame: Frame) {
|
|
207
|
+
val faces = session.getAllTrackables(AugmentedFace::class.java)
|
|
208
|
+
faces.forEach { face ->
|
|
209
|
+
val blendshapes = face.getBlendshapeCoefficients()
|
|
210
|
+
// blendshapes[AugmentedFace.BlendshapeCoefficient.MOUTH_OPEN] -> 0.0f - 1.0f
|
|
211
|
+
// Use these for avatar animation, accessibility features, etc.
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
\`\`\`
|
|
216
|
+
|
|
217
|
+
Source: https://developers.google.com/ar/develop/android-xr
|
|
218
|
+
`;
|
|
219
|
+
const deviceCompat = `
|
|
220
|
+
# Android XR — Device Compatibility & Non-XR Fallback
|
|
221
|
+
Source: https://developer.android.com/xr/develop/device-compatibility
|
|
222
|
+
|
|
223
|
+
## Running on Both XR and Non-XR Devices
|
|
224
|
+
|
|
225
|
+
Apps should work on standard Android phones AND XR devices. The pattern:
|
|
226
|
+
|
|
227
|
+
\`\`\`kotlin
|
|
228
|
+
// Compose — check XR environment at runtime
|
|
229
|
+
@Composable
|
|
230
|
+
fun AdaptiveApp() {
|
|
231
|
+
val isXrEnvironment = LocalXrEnvironment.current != null
|
|
232
|
+
|
|
233
|
+
if (isXrEnvironment) {
|
|
234
|
+
XrLayout() // Spatial panels, orbiters, 3D placement
|
|
235
|
+
} else {
|
|
236
|
+
StandardLayout() // Regular phone/tablet layout
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// ViewModel / Logic layer — no XR code here
|
|
241
|
+
// Architecture is identical to non-XR apps: MVVM, Repository, etc.
|
|
242
|
+
// XR is purely a presentation-layer concern
|
|
243
|
+
@HiltViewModel
|
|
244
|
+
class MainViewModel @Inject constructor(
|
|
245
|
+
private val userRepository: UserRepository
|
|
246
|
+
) : ViewModel() {
|
|
247
|
+
val uiState = userRepository.observeState().stateIn(
|
|
248
|
+
viewModelScope, SharingStarted.WhileSubscribed(5000), MainUiState()
|
|
249
|
+
)
|
|
250
|
+
}
|
|
251
|
+
\`\`\`
|
|
252
|
+
|
|
253
|
+
## Testing XR Apps Without Hardware
|
|
254
|
+
|
|
255
|
+
Use the Android XR Emulator in Android Studio:
|
|
256
|
+
1. SDK Tools → Android XR Emulator
|
|
257
|
+
2. Create AVD with XR device profile
|
|
258
|
+
3. Test both spatial and 2D fallback layouts
|
|
259
|
+
|
|
260
|
+
Source: https://developer.android.com/xr/develop/device-compatibility
|
|
261
|
+
`;
|
|
262
|
+
if (t.includes("setup") || t.includes("depend") || t.includes("install"))
|
|
263
|
+
return setup;
|
|
264
|
+
if (t.includes("spatial") || t.includes("panel") || t.includes("orbiter") || t.includes("subspace"))
|
|
265
|
+
return spatialUi;
|
|
266
|
+
if (t.includes("arcore") || t.includes("face") || t.includes("hand") || t.includes("plane") || t.includes("ar "))
|
|
267
|
+
return arcore;
|
|
268
|
+
if (t.includes("compat") || t.includes("fallback") || t.includes("non-xr") || t.includes("emulat"))
|
|
269
|
+
return deviceCompat;
|
|
270
|
+
return overview + "\n\n---\n\n" +
|
|
271
|
+
"**Query topics:** 'setup' (dependencies), 'spatial ui' (SpatialPanel, Orbiter, UserSubspace), " +
|
|
272
|
+
"'arcore' (face tracking, plane detection), 'compatibility' (XR + non-XR device support)\n\n" +
|
|
273
|
+
"Source: https://developer.android.com/xr";
|
|
274
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_what_is_this": "Google Antigravity is a standalone agentic AI IDE launched Nov 18 2025 alongside Gemini 3.",
|
|
3
|
+
"_not_firebase": "This is NOT Firebase Studio or Project IDX — those are separate Google products.",
|
|
4
|
+
"_download": "https://antigravity.google/download",
|
|
5
|
+
"_mcp_docs": "https://antigravity.google/docs/mcp",
|
|
6
|
+
"_instructions": [
|
|
7
|
+
"OPTION A – Via Antigravity UI (recommended, zero file editing):",
|
|
8
|
+
" 1. Open Antigravity",
|
|
9
|
+
" 2. In the Agent pane, click '...' (three dots) at the top",
|
|
10
|
+
" 3. Select MCP Servers → Manage MCP Servers",
|
|
11
|
+
" 4. Click 'View raw config'",
|
|
12
|
+
" This opens the mcp_config.json file directly in the editor.",
|
|
13
|
+
" 5. Add the 'androjack' block from mcpServers below and save.",
|
|
14
|
+
" 6. Return to Manage MCP Servers and refresh — AndroJack appears in your tool list.",
|
|
15
|
+
"",
|
|
16
|
+
"OPTION B – Edit the config file directly:",
|
|
17
|
+
" macOS / Linux: ~/.gemini/antigravity/mcp_config.json",
|
|
18
|
+
" Windows: C:\\Users\\<USER>\\.gemini\\antigravity\\mcp_config.json",
|
|
19
|
+
" (Create directories and file if they don't exist yet.)",
|
|
20
|
+
"",
|
|
21
|
+
"After saving, restart the Antigravity agent session or refresh MCP Servers."
|
|
22
|
+
],
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"androjack": {
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": [
|
|
27
|
+
"-y",
|
|
28
|
+
"androjack-mcp"
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Claude Desktop MCP Configuration for AndroJack",
|
|
3
|
+
"_instructions": [
|
|
4
|
+
"1. Open: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)",
|
|
5
|
+
" or: %APPDATA%\\Claude\\claude_desktop_config.json (Windows)",
|
|
6
|
+
"2. Merge the 'mcpServers' block below into that file.",
|
|
7
|
+
"3. Restart Claude Desktop.",
|
|
8
|
+
"4. Look for the hammer icon (🔨) in the chat input — that confirms MCP is active."
|
|
9
|
+
],
|
|
10
|
+
"mcpServers": {
|
|
11
|
+
"androjack": {
|
|
12
|
+
"command": "npx",
|
|
13
|
+
"args": ["-y", "androjack-mcp"],
|
|
14
|
+
"_note": "Uses npx — no global install needed. Downloads on first run."
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Cursor IDE MCP Configuration for AndroJack",
|
|
3
|
+
"_instructions": [
|
|
4
|
+
"OPTION A – Project-level (recommended for Android repos):",
|
|
5
|
+
" Place this file at: <your-android-project>/.cursor/mcp.json",
|
|
6
|
+
" Cursor will auto-detect it when you open the project.",
|
|
7
|
+
"",
|
|
8
|
+
"OPTION B – Global:",
|
|
9
|
+
" Mac/Linux: ~/.cursor/mcp.json",
|
|
10
|
+
" Windows: %USERPROFILE%\\.cursor\\mcp.json",
|
|
11
|
+
"",
|
|
12
|
+
"After saving, open Cursor → Settings → MCP to confirm 'androjack' appears with a green dot."
|
|
13
|
+
],
|
|
14
|
+
"mcpServers": {
|
|
15
|
+
"androjack": {
|
|
16
|
+
"command": "npx",
|
|
17
|
+
"args": ["-y", "androjack-mcp"],
|
|
18
|
+
"env": {}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|