A complete Android application scaffolding for a Tourism Intelligent Platform built with Kotlin, following Clean Architecture principles and modern Android development practices.
SmarTrip (módulo Android del ecosistema Voyager) es una aplicación que sigue buenas prácticas de Android moderno: arquitectura limpia, MVVM, inyección de dependencias (Hilt), red (Retrofit/Moshi), almacenamiento local y UI con Jetpack Compose, alineada con el cliente web voyager-web-client.
Key architectural decisions:
- Clean Architecture: Separation of concerns with distinct layers (Presentation, Domain, Data)
- MVVM Pattern: Model-View-ViewModel for UI state management
- Dependency Injection: Hilt for compile-time DI
- Reactive Programming: Kotlin Coroutines and Flow for async operations
- Modern UI: Jetpack Compose with Material Design 3
- Android Studio: Latest stable (recommended) with Kotlin 2.x and Compose support
- JDK: 17 (matches
compileOptions/kotlinOptionsin the app module) - Android SDK: API level 24+ (Android 7.0)
- Gradle: 9.5+ (via the included wrapper)
-
Clone the repository
git clone https://github.com/LePeanutButter/voyager-android.git cd voyager-android -
Open in Android Studio
# Alternatively, open Android Studio and select "Open an existing project" # Navigate to the cloned directory
-
Configure API endpoints
- Set base URLs in
gradle.properties(project root):VOYAGER_BACKEND_BASE_URL— Spring Boot API (must end with/api/v1/or the build will normalize it)VOYAGER_AI_BASE_URL— FastAPI AI service (must end with/api/v1/when applicable)
- Values are injected at build time as
BuildConfig.BACKEND_BASE_URLandBuildConfig.AI_SERVICE_BASE_URLand wired inNetworkModule.
- Set base URLs in
-
Build the project
./gradlew build
-
Run the application
./gradlew installDebug # Or run directly from Android Studio
# Build debug version
./gradlew assembleDebug
# Build release version
./gradlew assembleRelease
# Unit tests (JVM)
./gradlew :app:testDebugUnitTest
# Unit test coverage (Android Gradle Plugin report)
./gradlew :app:createDebugUnitTestCoverageReport
# JaCoCo HTML/XML (custom task; excludes UI/DI/generated noise — see app/build.gradle.kts)
./gradlew :app:jacocoTestReport
# Run instrumentation tests (device/emulator)
./gradlew connectedAndroidTest
# Clean build
./gradlew clean-
Launch from Android Studio
- Select the app module
- Choose a connected device or emulator
- Click the Run button
-
Command Line
./gradlew installDebug && adb shell am start -n com.voyager.tourism/.presentation.ui.splash.SplashActivity
// Login example
viewModel.login("user@example.com", "password123")
// Registration example
viewModel.register(
email = "user@example.com",
password = "password123",
username = "traveler",
firstName = "John",
lastName = "Doe"
)// Create a new trip
val trip = Trip(
id = UUID.randomUUID().toString(),
userId = "current-user-id",
title = "Paris Adventure",
description = "Weekend trip to Paris",
destination = Destination(/* ... */),
startDate = System.currentTimeMillis(),
endDate = System.currentTimeMillis() + 86400000,
budget = 1500.0,
travelers = 2
)
viewModel.createTrip(trip)// Navigate between screens
navController.navigate("dashboard")
navController.navigate("trip_detail/$tripId")
navController.navigate("recommendations")app/src/main/java/com/voyager/tourism/
- UI Components: Jetpack Compose screens and UI elements
- ViewModels: State management using AndroidX ViewModel
- Navigation: Jetpack Navigation Compose setup
- Entities: Core business models (User, Trip, Destination)
- Use Cases: Application business logic encapsulation
- Repository Interfaces: Data access contracts
- Repository Implementations: Concrete data access logic
- Data Sources: Remote (Retrofit) and local (Room) sources
- DTOs: Data transfer objects for API communication
- Interceptors: JWT attachment (
AuthInterceptor), session reset on401(UnauthorizedResponseInterceptor) - Session:
SessionInvalidationNotifierfor global sign-out flows
- Language: Kotlin 2.0.20
- UI Framework: Jetpack Compose with Material Design 3
- Architecture: MVVM with Clean Architecture
- Dependency Injection: Hilt 2.51
- Networking: Retrofit 2.9.0 + OkHttp 4.12.0 + Moshi 1.15.0
- Database: Room 2.6.1
- Async: Kotlin Coroutines 1.7.3
- Navigation: Navigation Compose 2.7.5
- Quality: JaCoCo (unit test coverage), JUnit 4, MockK, Robolectric (local prefs), AndroidX Test
app/
src/main/java/com/voyager/tourism/
|-- data/
| |-- api/ # Retrofit API services
| |-- database/ # Room database, entities, DAOs, Converters.kt
| |-- dto/ # Data transfer objects
| |-- interceptor/ # OkHttp interceptors (auth, unauthorized)
| |-- local/ # PreferencesManager, TokenManager
| |-- mapper/ # Domain/Data model mappers
| |-- repository/ # Repository implementations
| |-- session/ # Session invalidation signals (e.g. SharedFlow)
|-- domain/
| |-- model/ # Domain entities
| |-- repository/ # Repository interfaces
| |-- usecase/ # Business logic use cases
| | |-- auth/
| | |-- trip/
| | |-- behavior/
| | |-- recommendation/
| | |-- social/
|-- presentation/
| |-- MainActivity.kt
| |-- viewmodel/ # ViewModels
| |-- ui/ # Compose screens by feature
| | |-- auth/
| | |-- assistant/
| | |-- dashboard/
| | |-- trip/
| | |-- place/
| | |-- profile/
| | |-- recommendations/
| | |-- social/
| | |-- splash/
| |-- navigation/
|-- di/ # Hilt modules (Database, Network, Repository)
TourismApplication.kt # @HiltAndroidApp
- AI-Powered Travel Assistant: Personalized recommendations and trip planning
- User Authentication: Secure login/registration, Google OAuth flow, token and session handling
- Trip Management: Complete CRUD operations for travel itineraries
- Destination Discovery: AI-powered destination and activity recommendations
- Social Features: Connect with fellow travelers
- Offline Support: Local database caching with Room
- Modern UI: Material Design 3 with Jetpack Compose
- Clean Architecture: Scalable and maintainable codebase
- MVVM Pattern: Proper separation of UI and business logic
- Dependency Injection: Compile-time DI with Hilt
- Reactive Programming: Coroutines and Flow for async operations
- Local Storage: Room database for offline support
- Network Layer: Retrofit with OkHttp for API communication
- State Management: ViewModels with StateFlow and Compose state
POST /auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "password123"
}POST /auth/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "password123",
"username": "traveler",
"first_name": "John",
"last_name": "Doe"
}GET /trips?userId={userId}
Authorization: Bearer {token}POST /trips
Authorization: Bearer {token}
Content-Type: application/json
{
"title": "Paris Adventure",
"description": "Weekend trip to Paris",
"destination": { ... },
"start_date": 1640995200000,
"end_date": 1641081600000,
"budget": 1500.0,
"travelers": 2
}GET /recommendations/destinations?userId={userId}
Authorization: Bearer {token}POST /ai/chat
Authorization: Bearer {token}
Content-Type: application/json
{
"message": "What are the best places to visit in Paris?",
"context": "trip_planning"
}Prefer gradle.properties at the project root for service URLs consumed by the Android build:
# Backend (Spring Boot) — typically .../api/v1/
VOYAGER_BACKEND_BASE_URL=https://your-host:8080/api/v1/
# AI microservice (FastAPI) — typically .../api/v1/
VOYAGER_AI_BASE_URL=https://your-host:8000/api/v1/
# Optional broker URL for traveler chat real-time transport
VOYAGER_CHAT_BROKER_URL=wss://your-host/ws-chatOptional local.properties (not committed) can hold SDK paths and machine-specific overrides; keep secrets out of version control.
- Debug: Development build with logging, debugging, and unit test coverage instrumentation enabled (
enableUnitTestCoverage) - Release: Production build with optimizations (minify currently off by default — adjust as needed)
Key configurations in app/build.gradle.kts:
android {
compileSdk = 34
defaultConfig {
applicationId = "com.voyager.tourism"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0.0"
// BACKEND_BASE_URL / AI_SERVICE_BASE_URL from gradle.properties
}
}- Unit tests live under
app/src/test/javaand cover use cases, mappers, Room type converters, OkHttp interceptors, local session helpers, and ViewModels (with MockK and coroutine-friendly dispatchers). - Robolectric is used where Android
Contextis required (e.g.SharedPreferences-backed managers). - Coverage
./gradlew :app:createDebugUnitTestCoverageReport— full-module report underapp/build/reports/coverage/test/debug/./gradlew :app:jacocoTestReport— JaCoCo report with package exclusions for Compose UI,di, and generated/Hilt glue (seejacocoTestReportinapp/build.gradle.kts)
Overall coverage percentage is dominated by Compose UI and untested integration paths; interpret reports by package when gating quality on domain/data logic.
- Andrés Felipe Calderón Ramírez - AndresFelipeCalderonRamirez
- Laura Natalia Perilla Quintero - Lanapequin
- Ricardo Andres Ayala Garzon - lRicardol
- Santiago Amaya Zapata - SantiagoAmaya21
- Santiago Botero Garcia - LePeanutButter
This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.
- Commercial Use: Yes
- Modification: Yes
- Distribution: Yes
- Private Use: Yes
- Liability: No
- Warranty: No
© 2026 SmarTrip / Voyager. All rights reserved.