The essential tool for gun owners, hunters, and sport shooters in Spain. Tu Armeria helps you manage your firearm inventory, track ammunition quotas, and stay compliant with Spanish Gun Laws (Reglamento de Armas).
Generic gun apps don't understand the Spanish Guia de Pertenencia system or the strict ammo limits enforced by the Guardia Civil. This app does.
- Digital Firearm Inventory — Organize all your firearms with make, model, caliber, serial number, and photos. Each weapon linked to its Guia de Pertenencia and License Type (B, C, D, E, F, AEM).
- Ammunition Quota Tracker — Track purchases against your legal yearly limit. Visual alerts when approaching storage caps. Shooting range purchases are automatically exempt from quota per Spanish regulation.
- License & Renewal Management — Calendar integration with reminders for license expiry, mandatory inspections (Revista de Armas), insurance, and federation cards.
- Championship & Shooting Log — Manage competition dates, log scores (Precision 0-600 / IPSC 0-100%), and track participation for F License renewals.
- Offline-First with Cloud Sync — Works without internet. Data syncs automatically to Firebase when connectivity is available.
- Multi-language — Spanish and English.
The app follows MVVM + Clean Architecture with an offline-first approach:
UI Layer (Compose) Domain Layer Data Layer
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Screens │ │ Use Cases │ │ Repositories │
│ ViewModels │───>│ Business Logic │───>│ Room (SQLite) │
│ Navigation │ │ Validation │ │ Firebase RTDB │
│ State (MVI) │ │ │ │ Firebase Storage │
└──────────────────┘ └──────────────────┘ └──────────────────┘
Key design decisions:
- Room is the source of truth. Firebase provides cloud backup and cross-device sync.
- Type-safe navigation with custom
NavTypeand@Serializableroutes — full objects are passed between screens, eliminating race conditions from ID-based lookups. - MVI pattern in form screens — unidirectional data flow with events, state, and one-shot effects.
| Category | Technology |
|---|---|
| Language | Kotlin 2.3 (K2 compiler) |
| UI | Jetpack Compose + Material Design 3 |
| Navigation | Navigation Compose 2.9 (type-safe routes) |
| DI | Hilt 2.59 |
| Local DB | Room 2.8 |
| Async | Kotlin Coroutines + Flow |
| Images | Coil 2.7 (loading) + Firebase Storage (persistence) |
| Serialization | kotlinx.serialization |
| Background | WorkManager 2.11 |
| Security | AndroidX Biometric + EncryptedSharedPreferences |
| Testing | JUnit 5 + MockK + Espresso |
| Leak Detection | LeakCanary (debug only) |
| Service | Purpose |
|---|---|
| Authentication | Email/password and anonymous sign-in |
| Realtime Database | Cloud sync with offline persistence |
| Storage | Full-size firearm and purchase photos |
| Crashlytics | Crash reporting with PII-redacted metadata |
| Analytics | Usage tracking |
| Cloud Messaging | Push notifications |
- Android Studio Ladybug or newer
- JDK 17+
- A Firebase project (setup guide)
# Clone the repository
git clone https://github.com/foliolo/Municion.git
cd Municion
# Place your Firebase config
cp /path/to/your/google-services.json app/
# Create keystore.properties for release builds (optional)
cat > keystore.properties << EOF
keyAlias=your_alias
keyPassword=your_password
storeFile=/path/to/keystore.jks
storePassword=your_store_password
EOF
# Build debug
./gradlew assembleDebug
# Install on connected device
./gradlew installDebugThe app requires a Firebase project with:
- Authentication — Enable Email/Password and Anonymous providers
- Realtime Database — Create a database instance
- Storage — Enable Cloud Storage for image uploads
- Crashlytics — Enable in the Firebase console
Place your google-services.json in the app/ directory.
The app manages 4 entities stored as arrays under users/{uid}/db/ in Firebase:
| Entity | Spanish | Description |
|---|---|---|
| Licencia | Licencia | Firearms license with expiration tracking |
| Guia | Guia | Firearm permit linked to a license, with annual ammo quota |
| Compra | Compra | Ammunition purchase linked to a Guia |
| Tirada | Tirada | Shooting competition/event record |
Key relationship: Each Guia has an annual quota (cupo). Purchases in stores consume quota; purchases at shooting ranges are exempt per Spanish law. Quota resets every January 1st.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request against
develop
This project is for personal and educational use. See the repository for details.
Made with ☕ in Spain