README.md

Android UI Behavior Analyzer

A suite of two Claude Code custom agents that analyze Android app UI code to extract all user interactions, navigation flows, data dependencies, and side effects — then derive functional requirements checklists from the analysis.

Agent Target Input
android-activity-ui-behavior-analyzer Traditional View system (Activity + XML layouts) Android project path
compose-ui-behavior-analyzer Jetpack Compose (@Composable screens) Android project path + compose-ui-tree-analyzer output

Quick Start

# Traditional View system (Activity + XML)
@android-activity-ui-behavior-analyzer /path/to/android/project [/path/to/output]

# Jetpack Compose
@android-compose-ui-behavior-analyzer /path/to/android/project /path/to/compose-ui-analysis /path/to/output

What They Do

From an Android project's source code, both agents answer:

  • What can the user do on each screen?
  • What happens when they tap each button / menu item / list item?
  • Does it navigate to another page? Show a dialog? Call the camera? Delete a file?
  • What APIs / data sources power each screen's initial content?
  • What are the app's functional requirements, derived from UI behavior?

Architecture

Both agents follow the same 3-phase pipeline:

Phase 1:  Python static analyzer  → structured JSON (automated, ~56-58% fill rate)
Phase 2:  Claude deep analysis    → enhanced JSON (MANDATORY, target ≥90%)
Phase 3:  Claude report writing   → functional_report.md + requirements_checklist.md

Activity Analyzer Pipeline

Phase 1: Python Script (automated)          Phase 2: Claude (mandatory)
┌────────────────────────────────┐      ┌──────────────────────────────┐
│  android_ui_api_analyzer.py    │      │  Deep Semantic Analysis       │
│                                │      │                              │
│  AndroidManifest.xml ──┐       │      │  Read JSON ──┐              │
│  res/layout/*.xml ─────┤       │      │  Categorize  │ A: toast     │
│  res/menu/*.xml ───────┤       │ JSON │  empty items │ B: toggle    │
│  *.kt / *.java ────────┤       │ ───► │              │ C: parent    │
│                        │       │      │  Read source │ D: CAB       │
│  → Activities from Manifest    │      │  Trace calls │ E: misc      │
│  → ~58% nav filled             │      │  Update JSON │              │
│  → Page data loaders           │      │  → ≥90% nav  │              │
└────────────────────────────────┘      └──────┬───────────────────────┘
                                               │
                                               ▼
                                   Phase 3: Claude (report writing)
                                   ┌──────────────────────────┐
                                   │  functional_report.md    │
                                   │  requirements_checklist  │
                                   └──────────────────────────┘

Compose Analyzer Pipeline

Phase 1: Python Script (automated)          Phase 2: Claude (mandatory)
┌────────────────────────────────┐      ┌──────────────────────────────┐
│  compose_ui_behavior_analyzer  │      │  Deep Semantic Analysis       │
│                                │      │                              │
│  discovery.json ───────┐       │      │  Read JSON ──┐              │
│  pages/*.json ─────────┤       │      │  Categorize  │ A: nav route │
│  source_analyses/*.json┤       │ JSON │  empty items │ B: ViewModel │
│  viewmodels/*.json ────┤       │ ───► │              │ C: dialog    │
│  *.kt source ──────────┤       │      │  Read source │ D: toggle    │
│                        │       │      │  Trace calls │ E: external  │
│  → Recursive composable expand │      │  Update JSON │ F: player    │
│  → ~56% nav filled             │      │  → ≥90% nav  │              │
│  → 353+ indexed @Composable    │      │              │              │
└────────────────────────────────┘      └──────┬───────────────────────┘
                                               │
                                               ▼
                                   Phase 3: Claude (report writing)
                                   ┌──────────────────────────┐
                                   │  functional_report.md    │
                                   │  requirements_checklist  │
                                   └──────────────────────────┘

4-Column Navigation Classification

Every UI interaction is classified across 4 dimensions (shared by both agents):

Column What it captures Example Values
Navigation Page-level jumps → SettingsActivity, → ScreenRoute.XXX, → [Back]
Screen Change In-page state changes Dialog: ChangeSortingDialog, UI: toggle, Refresh: adapter
External System/external calls Camera: system, Share: ACTION_SEND, Browser: URL
Side Effect Persistent effects FS: delete, DB: write, Playback: play/pause

A single interaction can fill multiple columns. Example: a delete button may have Navigation: → [Back] + Screen Change: Dialog + Side Effect: FS: delete.

Output Files

Both agents produce the same 3-file output structure:

<output_dir>/
├── <analysis>.json              # Structured JSON evidence (Phase 1 + Phase 2)
├── functional_report.md         # Per-screen: description + interaction table + data loading table
└── requirements_checklist.md    # Functional requirements grouped by feature area
File Activity Analyzer Compose Analyzer
JSON ui_api_analysis.json compose_ui_behavior.json
Report functional_report.md functional_report.md
Checklist requirements_checklist.md requirements_checklist.md

JSON Structure

Activity analyzer — per Activity:

  • ui_components[] — actionable components with 4-column targets + API dependencies
  • page_data_loading_entries[] — lifecycle/init methods that load page data
  • functional_evidence[] — manifest, layout, fragment evidence
  • fragment_analyses[] — nested fragment component analysis

Compose analyzer — per Screen:

  • interactive_components[] — @Composable components with 4-column targets + ViewModel methods
  • data_loading_entries[] — LaunchedEffect, collectAsState, remember bindings
  • viewmodel_bindings[] — ViewModel state and method references

functional_report.md

Per-screen sections with:

  • Screen Functional Description (2-4 paragraphs)
  • UI Component Interaction Table (11-12 columns)
  • Page-Level Data Loading Table

requirements_checklist.md

Functional requirements grouped by area:

FR-001: Gallery Browsing
  Screen: MainActivity
  Interactions: tap folder → MediaActivity, pull to refresh, search
  Data Source: MediaFetcher → MediaStore query
  Side Effects: none

Agent Comparison

Activity Analyzer Compose Analyzer
Target UI Traditional View system (XML layouts) Jetpack Compose (@Composable)
Entry point AndroidManifest.xml → Activities discovery.json → Screens
Layout source res/layout/*.xml, res/menu/*.xml @Composable functions in .kt
Event binding setOnClickListener, onOptionsItemSelected, XML onClick onClick, onLongClick, onChange, Modifier.clickable
Navigation startActivity(Intent(...)), finish() navController.navigate(ScreenRoute.XXX), popBackStack()
Data loading onCreate, onResume, custom loadData methods LaunchedEffect, collectAsState, remember
State management SharedPreferences, Room DAO, direct field access ViewModel + StateFlow, DataStore, MMKV/AppConfig
Phase 1 script android_ui_api_analyzer.py compose_ui_behavior_analyzer.py
Phase 2 categories A-E (toast, toggle, parent/ext, CAB, misc) A-F (nav route, ViewModel, dialog, toggle, external, player)
Prerequisites Android project only Android project + compose-ui-tree-analyzer output
Python script scripts/android_ui_api_analyzer.py scripts/compose_ui_behavior_analyzer.py

Phase 2: How Claude Fills the Gaps

Both Phase 1 scripts use regex and static analysis — they find who is clicked but often can't trace what happens when the handler calls an indirect method. Phase 2 categorizes empty-navigation components and handles each systematically.

Activity Analyzer Categories

Category Pattern Claude Action
A (~60) setOnLongClickListener { toast(...) } Set Screen Change: UI: toast("text")
B (~31) Settings toggle → config.xxx = !config.xxx Set UI: toggle + DB: write (config)
C (~13) Menu → parent/extension method Trace across inheritance + extension files
D (~27) CAB action → adapter method Read adapter, trace actionItemPressed branches
E (~35) Editor/panorama buttons → mode switch Read method body, classify action

Compose Analyzer Categories

Category Pattern Claude Action
A (~40%) Item(onClick = { navController.navigate(...) }) Extract route from lambda
B (~25%) onClick calls ViewModel method Read ViewModel, determine effect
C (~15%) showXxxDialog = true Set Screen Change: Dialog: XxxDialog
D (~10%) ItemSwitcher / ItemCheck toggle Set UI: toggle + Config: write
E (~5%) External intent (share, browser, email) Read handler, set External
F Player controls (play, pause, seek, etc.) Read PlayerViewModel, set effects

Files

Agents/android-ui-behavior-analyzer/
├── README.md                                   # This file
├── android-activity-ui-behavior-analyzer.md    # Agent: traditional View system
├── compose-ui-behavior-analyzer.md             # Agent: Jetpack Compose
└── scripts/
    ├── android_ui_api_analyzer.py              # Python analyzer for Activity + XML
    └── compose_ui_behavior_analyzer.py         # Python analyzer for Compose

Requirements

  • Python 3.10+ (standard library only, no pip dependencies)
  • Claude Code for Phase 2 deep semantic analysis and Phase 3 report writing

Activity Analyzer

  • Android project source with app/src/main/AndroidManifest.xml

Compose Analyzer

  • Android project source with app/src/main/
  • compose-ui-tree-analyzer output (contains discovery.json, pages/*.json, source_analyses/*.json, viewmodels/*.json)

Iron Rules (Shared)

  1. JSON first — read the analyzer JSON before opening source files
  2. Source-backed claims only — every claim traces to analyzer output or source code
  3. Declaration-level output only — do not narrate runtime values or full dataflow
  4. Prefer nearest verified declaration — if tracing stops at Repository.getAlbums(), output that
  5. Keep uncertainty visible — use N/A or cautious phrasing when evidence is weak
  6. Deep semantic analysis is MANDATORY — Phase 2 must execute for every screen. Target >= 90% fill rate
  7. Full code surface — analyze all relevant source files (parent classes, extensions, adapters, ViewModels, dialogs)
  8. No fabrication — only output what exists in source code
  9. 4-column navigation — always classify targets into Navigation / Screen Change / External / Side Effect
  10. No confirmation needed — full read/write access, proceed without asking
  11. Categorize before tracing — group empty components by pattern before reading source files

Comparison with android-ui-tree-analyzer

android-ui-tree-analyzer android-ui-behavior-analyzer
Goal UI layout hierarchy (view tree) UI behavior + functional requirements
Output JSON with nested view_tree per Activity/Screen Interaction tables + requirements checklist
Focus Component types, attributes, nesting Click events, navigation, data flow, side effects
Use case HarmonyOS ArkTS UI conversion Feature/requirement documentation
Navigation Single navigates_to field 4 columns: Navigation / Screen Change / External / Side Effect
API tracing None DAO, Retrofit, ContentResolver, ViewModel, MediaStore, system intents
Data loading None Lifecycle init + LaunchedEffect / collectAsState analysis

Known Limitations

Shared

  1. Phase 1 scripts cover ~56-58% of navigation targets — Phase 2 (Claude) is required to reach 90%+
  2. Reflection / dynamic registration — event handlers registered via reflection are not detected
  3. Deep indirect calls (>3 levels) — call chain tracing stops at depth 2-3
  4. Third-party library callbacks — internal behavior of libraries (Glide, ExoPlayer, etc.) not traced
  5. Runtime-conditional behavior — all code paths reported; cannot determine which runs at runtime

Activity Analyzer Only

  1. Compose UI — Jetpack Compose @Composable functions are not analyzed (use compose-ui-behavior-analyzer instead)

Compose Analyzer Only

  1. Requires compose-ui-tree-analyzer output — must run compose-ui-tree-analyzer first to generate the input data
  2. Custom composable expansion depth — recursive expansion stops at 2 levels deep