Accessible shopping list app for Android. Designed for elderly users and anyone who values clarity over clutter.
I built this for my mom. She struggles with most shopping list apps — tiny buttons, cluttered interfaces, ads everywhere, and apps that collect data they don't need. So I made one that does the opposite.
![]() Main screen |
![]() Create list |
![]() View list |
![]() Edit list |
![]() Buy mode |
![]() Buy mode (prices) |
![]() Help |
![]() Purchase history |
![]() Share list |
- Create and manage shopping lists with quantities and prices
- "Buy mode" that learns real prices as you shop
- Purchase history with totals
- Available in 16 languages
- Dark mode built in
- Accessibility-first design: large buttons, readable typography, high contrast
- No personal data collection: only Google AdMob receives standard advertising identifiers (with GDPR consent via UMP)
- Share lists via WhatsApp, Telegram, email, or any messaging app
- Language: Kotlin
- UI: Jetpack Compose with Material 3
- Architecture: Single-activity, navigation with NavHost
- Persistence: SharedPreferences (lightweight, app-local)
- Monetization: Google AdMob with UMP consent (GDPR compliant)
- Min SDK: 26 (Android 8.0+)
- Target SDK: 35
- Migrated from a v1 prototype with a memory leak (AdView instances leaking WebView contexts) to a v2 with proper lifecycle management
- Security-audited: no telemetry, no tracking, minimal permissions
- Validated input handling — no crashes from edge cases
- Code minified and obfuscated with R8 in release builds (~65% size reduction from v1)
- Full internationalization in 16 languages
This app went through 8 iterations of polishing before its v2.0 release. A few decisions worth highlighting:
- Cross-screen consistency: unified design language across all screens (cards, typography, color palette)
- i18n via universal button asset: instead of using semantic icons (which would multiply asset count by 16 languages), text overlays on a single decorative button image. One asset, sixteen languages.
- Race condition prevention: an
isSavingflag prevents double-tap duplicate creations - Persistent price learning: prices update immediately during shopping, even if the purchase is cancelled — the app "learns" real market prices over time
The repo is buildable as-is, but signing the release variant requires a few credentials kept outside the project tree.
- Clone and open in Android Studio (Hedgehog or newer recommended).
- For a debug build: just run. AdMob uses Google's sample/test IDs in debug, so tapping ads is safe.
- For a signed release build, copy
gradle.properties.templateto~/.gradle/gradle.properties(or%USERPROFILE%\.gradle\gradle.propertieson Windows) and fill in your keystore values. Keep the.jksfile outside the project.
If signing credentials are missing, the release build will still compile (unsigned) with a warning — useful for CI.
Arabic, Bengali, Chinese, English, French, German, Hindi, Indonesian, Italian, Japanese, Portuguese, Russian, Spanish, Urdu, Vietnamese, plus the default (English).
GoodListPlus does not collect personal data. The only third-party service is Google AdMob, which receives standard advertising identifiers as documented in Google's privacy policy.
Users can manage advertising consent at any time from within the app (GDPR compliant via the UMP SDK).
Apache 2.0 — see LICENSE for details.
For feedback, bug reports, or feature requests: david.system80@gmail.com
Built with care, in the margins of a warehouse worker's life.









