This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
AutoAction is an Android automation app that uses AccessibilityService to enable script-based screen interactions (clicks, swipes, multi-touch) without requiring root access. The app targets gaming scenarios (particularly MOBA games) where users need rapid, repeatable macro operations.
- Visual script recording via transparent overlay capture
- Script library management with independent floating shortcuts
- Atomic action model (CLICK, SWIPE, DELAY) with randomization support
- Multi-instance floating windows for quick macro execution
Navigate to the app/ directory for all Gradle commands:
cd app/
# Build the app
./gradlew assembleDebug
# Install debug build to connected device
./gradlew installDebug
# Run tests
./gradlew test # Unit tests
./gradlew connectedAndroidTest # Instrumented tests
# Clean build
./gradlew clean
# Lint check
./gradlew lint
# Build release APK
./gradlew assembleRelease- Language: Kotlin
- UI Framework: Jetpack Compose (modern screens) + XML ViewBinding (legacy fragments)
- Architecture: MVVM pattern
- Database: Room (local SQLite)
- DI: Manual dependency injection via service singletons
- Async: Coroutines with Flow for reactive data streams
AutoActionService.kt - Core accessibility service
- Implements
AccessibilityServiceto dispatch gestures - Maintains singleton instance accessible via
getInstance() - Hosts
ScriptExecutorfor running automation scripts - Communicates service status via
StateFlow
ScriptExecutor.kt - Script orchestration
- Manages script lifecycle (start, loop, stop)
- Delegates gesture execution to
GestureExecutor - Applies global randomization settings per-script
- Handles loop modes: infinite (count=0) or finite (count=N)
GestureExecutor.kt - Low-level gesture dispatch
- Translates
Actiondata classes into AndroidAccessibilityNodeInfo.GestureDescription - Applies coordinate offset and duration variance for anti-detection
FloatingWindowService.kt - Overlay manager
- Creates two types of floating UI:
- Control Bar: Global controls (recording, settings, shortcut toggle)
- Script Shortcuts: Individual floating buttons per enabled script
- Uses
WindowManagerwithTYPE_APPLICATION_OVERLAY - Implements touch disambiguation: <40px movement = click, ≥40px = drag
- Persists shortcut positions to database on drag completion
RecordingService.kt - Gesture capture
- Overlays full-screen transparent layer to intercept
MotionEvent - Converts touch sequences into
Actionobjects with calculated delays - Blocks underlying app interaction during recording (standard Android limitation)
Room Database (AppDatabase.kt)
- Single entity:
ScriptEntity(JSON-serialized fields foractions,shortcutConfig) - DAO operations exposed as
Flowfor reactive UI updates
Data Models (in data/model/)
Script: Domain model containing action list, loop config, randomization paramsAction: Atomic instruction with type (CLICK/SWIPE/DELAY), coordinates, durationShortcutConfig: Floating button appearance (icon, position, alpha, scale)ActionType: Enum defining supported gesture primitives
Settings Layer (data/settings/)
GlobalSettings: Data class for app-wide randomization parametersSettingsRepository: DataStore-backed persistence for global settings
Repository (ScriptRepository.kt)
- Abstracts database access
- Provides
enabledScriptsFlow for observing active shortcuts - Handles entity ↔ domain model conversion
Compose Screens (ui/screen/)
ScriptListScreen: Main list with accessibility service status indicatorScriptEditorScreen: Visual action sequence editor with drag-to-reorderSettingsScreen: Global randomization and anti-detection settings
Navigation (ui/navigation/NavGraph.kt)
- Simple Compose Navigation with three routes:
script_list(home)script_editor/{scriptId}(create/edit)settings(global settings)
ViewBinding Fragments (legacy, in ui/home/, ui/dashboard/, etc.)
- Older XML-based fragments for settings/notifications
- Coexist with Compose screens during migration
The original design coupled clicks with delays (baseDelay field). v2.0 refactored to atomic actions:
- Old:
CLICK(x=100, y=200, baseDelay=1000) - New:
CLICK(x=100, y=200, duration=50)+DELAY(duration=1000)
This enables advanced patterns like "continuous taps without pause" or "hold button indefinitely."
Global settings (stored in DataStore via SettingsRepository):
randomization_enabled: Master toggle (default: false)click_offset_radius: ±N pixels from target coordinates (default: 10px, range: 0-50)click_duration_variance: ±N milliseconds for click/swipe duration (default: 50ms, range: 0-200)delay_variance: ±N milliseconds for delay actions (default: 100ms, range: 0-1000)haptic_feedback_enabled: Vibration feedback toggle (default: true)
Three-tier override hierarchy:
- Global settings: App-wide defaults from
SettingsRepository - Script-level settings:
Script.globalRandomOffsetandScript.globalRandomDelayoverride global values - Action-level overrides:
Action.overrideRandomOffsetandAction.overrideRandomDelayoverride both
Variance is bidirectional (±): A setting of 78ms means random value in [-78, +78].
Execution flow: GestureExecutor receives GlobalSettings from ScriptExecutor, applies randomization only when randomization_enabled == true, using coerceAtLeast() to ensure script/action overrides respect global minimums.
Shortcut buttons (ScriptShortcutContent):
ACTION_DOWN: Record initial touch positionACTION_MOVE: If movement exceeds 40px threshold → enter drag modeACTION_UP:- If not dragging AND movement <40px → execute script
- If dragging → save new position to database
Position memory: Each script's shortcutConfig.screenX/Y persists across app restarts.
- Add enum value to
ActionType.kt - Update
Actiondata class with required parameters - Modify
GestureExecutor.ktto handle new gesture dispatch:- Add case in
executeAction()when block - Implement execution function (e.g.,
executeCustomAction()) - Apply randomization if needed
- Add case in
- Update
ScriptEditorScreen.ktUI:- Add menu item in FAB dropdown with icon
- Add editing UI in
ActionCardwhen block - Update action preview text in card summary
- Update
RecordingService.ktif action should be recordable - Add database migration if changing
Actionschema
- Entry point:
AutoActionService.executeScript(scriptId) - Loop control: Edit
ScriptExecutor.executeScript() - Gesture customization: Modify
GestureExecutor.executeAction()
- Accessibility services cannot be easily mocked
- Use instrumented tests on real devices (not emulators) for full gesture testing
- Manual testing requires:
- Enabling "AutoAction" in Settings → Accessibility
- Granting "Display over other apps" permission
- Monitoring logcat for gesture dispatch failures
Essential runtime permissions (must guide users to grant):
SYSTEM_ALERT_WINDOW- Floating windowsBIND_ACCESSIBILITY_SERVICE- Gesture dispatchREQUEST_IGNORE_BATTERY_OPTIMIZATIONS- Background stabilityFOREGROUND_SERVICE- Recording/execution persistence
- Recording blocks interaction: Transparent overlay intercepts all touch events during recording - cannot operate target app simultaneously
- Gesture dispatch limits: AccessibilityService has ~100ms minimum delay between gestures on some devices
- View hierarchy dependency: Some advanced features (like "tap element by text") require parsing accessibility node tree, not yet implemented
- No root features: Cannot simulate hardware keys (volume, power) or bypass secure screens
Completed on 2023-12-12 - Full v2.0 atomic action refactoring:
- Global Settings Module: Added DataStore-backed
SettingsRepositorywith UI inSettingsScreen - Atomic Action Model: Deprecated
Action.baseDelayin favor of separateDELAYactions - Script Editor Enhancements:
- FAB now opens dropdown menu for CLICK/SWIPE/DELAY
- Removed baseDelay from CLICK editor
- Added complete SWIPE parameter editor (startX/Y, endX/Y, duration)
- Renamed DELAY label to "Wait Duration" for clarity
- Randomization Improvements: Three-tier override system (global → script → action)
- Old scripts with
baseDelay != 0still work but show deprecation warnings - To convert: manually split into
Action(type=CLICK, duration=X)+Action(type=DELAY, duration=Y) - Recording service automatically creates DELAY actions between gestures
See docs/ directory for detailed specifications:
requirements.md: Original PRD with macro mode requirementsdesign_v2_refinement.md: Atomic action model and global settings designui_design.md: Screen wireframes and interaction flows
- Respect the atomic action model: Never add
baseDelaylogic to new code - Test randomization: Always test with
randomization_enabled = trueto verify variance application - Preserve floating window positions: Ensure any changes to
FloatingWindowServicemaintain the 40px drag threshold - Use descriptive action labels: When creating actions programmatically, set meaningful
descvalues for debugging