Developing Android Apps
YAML--- name: developing-android-apps description: Analyzes Android app requirements, proposes implementation approaches, generates use cases, writes Java-based Android code, and iteratively tests and fixes bugs based on user feedback. Use when building a new Android app from requirements, extending an existing Android app, or debugging and refining an Android app through user-driven feedback cycles. --- # Developing Android Apps
Given a user's app idea, don't start coding immediately. Follow this sequence:
- Clarify requirement → ask only essential questions if the ask is ambiguous
- Propose approaches → 2-3 implementation options with tradeoffs
- Get selection → user picks one (or you recommend a default if they say "you decide")
- Generate use cases → list actors, flows, edge cases
- Code → build the feature using Java (Kotlin only if user explicitly prefers it)
- Deliver + list features → show what's working, what's available to test
- Iterate → take user feedback/bug reports, fix, redeliver
Example kickoff response to "I need a simple to-do app":
Implementation options:
1. Local-only (Room DB + RecyclerView) — fast, offline, no backend. Best for simple/personal use.
2. Local + Cloud sync (Room + Firebase Firestore) — adds login & multi-device sync, more setup.
3. Minimal (SharedPreferences + ArrayList) — fastest to build, no persistence guarantees for complex data.
Recommended: Option 1 (Room + RecyclerView) — matches "simple" scope, no backend dependency.
Proceed with this, or prefer option 2/3?
Progress:
- [ ] Step 1: Requirement analysis & clarification
- [ ] Step 2: Present implementation options, get user decision
- [ ] Step 3: Generate use cases (actors, flows, edge cases, acceptance criteria)
- [ ] Step 4: Define architecture (package structure, data layer, UI layer)
- [ ] Step 5: Implement code incrementally (data layer → logic → UI)
- [ ] Step 6: Self-test (unit logic, null/edge cases, build check)
- [ ] Step 7: Deliver feature list + how to test manually
- [ ] Step 8: Collect user feedback / bug reports
- [ ] Step 9: Fix bugs, re-verify, redeliver
Step 1: Requirement Analysis
Extract: core purpose, target users, must-have features vs nice-to-have, platform constraints (min SDK, offline/online), data persistence needs. If the user says "simple," default to the leanest viable architecture — don't over-engineer.
Step 2: Implementation Options
Always give a default recommendation, not just a menu. Base tradeoffs on: setup time, scalability, offline support, learning curve. Let the user pick or defer to your judgment ("let AI decide" = pick the recommended default silently and proceed).
Step 3: Use Case Generation
For each major feature, produce:
Use Case: Add Task
Actor: User
Precondition: App is open on main screen
Flow:
1. User taps "+" button
2. User enters task title
3. User taps Save
4. Task appears in list, persisted to DB
Alternate/Edge:
- Empty title → show validation error, don't save
- DB write failure → show retry toast
Postcondition: Task list updated and persisted
Step 4: Architecture
Default stack unless specified otherwise:
- Language: Java
- Pattern: MVVM (ViewModel + LiveData) for anything beyond trivial, plain Activity/Fragment for truly simple single-screen apps
- Persistence: Room for structured local data, SharedPreferences for flags/settings
- UI: XML layouts + RecyclerView for lists, ViewBinding (not findViewById) for new code
- Package by feature (
com.app.tasks,com.app.auth) not by layer, once app exceeds ~3 screens
Step 5: Implementation
Build bottom-up: Model/Entity → DAO/Repository → ViewModel → UI. Keep each piece compilable before moving to the next — don't write the whole app in one unverified block.
Step 6: Self-Test Before Delivery
- Check null/empty inputs, rotation (config change) survival, back-press behavior
- Verify Gradle build mentally (correct imports, matching dependency versions)
- Check for obvious main-thread DB/network violations
Step 7: Deliver
Always end a delivery with:
Features implemented:
✅ Add/edit/delete task
✅ Persisted via Room
✅ Mark complete/incomplete
How to test:
- Launch app → tap "+" → add task → verify it appears
- Long-press task → delete → verify removal
- Rotate device → verify list persists
Known limitations / not yet done:
- No due dates
- No cloud sync
Step 8-9: Feedback Loop
When user reports a bug: reproduce mentally from their description first, state root-cause hypothesis, then fix. Always confirm fix addresses the reported symptom, not just a related issue.
Example 1: Input: "I need a simple app its requirements are analyzed with use cases and then app is build" (notes app, no further detail)
Output:
Clarifying assumption (proceeding unless corrected): single-user, offline, text notes with title+body, no categories/sync.
Options:
1. Room DB + RecyclerView (recommended) — persistent, simple, standard Android pattern
2. SharedPreferences + JSON serialization — simpler but poor for growing data
Proceeding with Option 1.
Use Cases:
- Create Note (title, body, timestamp)
- Edit Note
- Delete Note (swipe-to-delete)
- View Note List (sorted by last modified)
Architecture: MVVM, Room entity `Note(id, title, body, timestamp)`, NoteDao, NoteRepository, NoteViewModel, MainActivity (RecyclerView), AddEditActivity.
[code delivered incrementally: Entity → Dao → Repository → ViewModel → Activities/Adapter]
Features implemented: ✅ Create ✅ Edit ✅ Delete ✅ List sorted by date
Test: Launch → tap + → write note → save → see it in list → tap to edit → swipe to delete.
Known limitations: no search, no categories.
Example 2: Input: "App crashes when I rotate the screen on the add note page"
Output:
Root cause hypothesis: Activity recreation on rotation wipes unsaved EditText state / ViewModel not scoped correctly, likely NullPointerException on re-binding.
Fix: Move form state into ViewModel (survives config change), use onSaveInstanceState as fallback for raw EditText drafts.
[code fix delivered]
Verification: Rotate device mid-typing → text persists → no crash → save still works.
- Default to Java unless user states a Kotlin preference; don't ask every time.
- Never silently expand scope — if "simple app" could imply login/sync, ask once, then lock scope.
- Keep use cases traceable to features in the final delivery list — nothing delivered should lack a use case, and vice versa.
- Favor Room over raw SQLite, ViewModel+LiveData over manual callbacks, for anything with state across configuration changes.
- Always state known limitations explicitly — don't let user discover missing scope via a bug report.
- When fixing bugs, state the hypothesis before the fix so the user can correct misdiagnosis early.
- Jumping straight to code without presenting options/use cases first — breaks the expected workflow.
- Delivering a feature list that doesn't map to discussed use cases.
- Using deprecated APIs (AsyncTask, findViewById without ViewBinding) in new code.
- Doing DB/network calls on the main thread.
- Ignoring configuration-change survival (rotation) — a very common Android bug source.
- Treating every bug fix as a full rewrite instead of a targeted, verifiable patch.
- Over-engineering a "simple" app with unnecessary architecture (DI frameworks, multi-module setup) when not requested.