From dea0ee498b332db47b4651befee8f523e326b19b Mon Sep 17 00:00:00 2001 From: ale Date: Sun, 13 Jul 2025 18:22:17 +0200 Subject: [PATCH] initial commit Signed-off-by: ale --- .gitignore | 16 + .idea/.gitignore | 3 + .idea/AndroidProjectSystem.xml | 6 + .idea/compiler.xml | 6 + .idea/deploymentTargetSelector.xml | 10 + .idea/gradle.xml | 19 + .idea/migrations.xml | 10 + .idea/misc.xml | 10 + .idea/runConfigurations.xml | 17 + .idea/vcs.xml | 6 + README.md | 200 ++++++++++ app/.gitignore | 1 + app/build.gradle.kts | 65 ++++ app/proguard-rules.pro | 21 ++ .../location/ExampleInstrumentedTest.kt | 24 ++ app/src/main/AndroidManifest.xml | 28 ++ app/src/main/ic_launcher-playstore.png | Bin 0 -> 12589 bytes .../manalejandro/location/LocationService.kt | 138 +++++++ .../location/LocationViewModel.kt | 176 +++++++++ .../com/manalejandro/location/MainActivity.kt | 344 ++++++++++++++++++ .../manalejandro/location/ui/theme/Color.kt | 11 + .../manalejandro/location/ui/theme/Theme.kt | 58 +++ .../manalejandro/location/ui/theme/Type.kt | 34 ++ app/src/main/res/images/location.png | Bin 0 -> 1471 bytes .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + app/src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 0 -> 1386 bytes .../mipmap-hdpi/ic_launcher_foreground.webp | Bin 0 -> 1892 bytes .../res/mipmap-hdpi/ic_launcher_round.webp | Bin 0 -> 3000 bytes app/src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 0 -> 934 bytes .../mipmap-mdpi/ic_launcher_foreground.webp | Bin 0 -> 954 bytes .../res/mipmap-mdpi/ic_launcher_round.webp | Bin 0 -> 1922 bytes .../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 0 -> 1916 bytes .../mipmap-xhdpi/ic_launcher_foreground.webp | Bin 0 -> 2678 bytes .../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 0 -> 4358 bytes .../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 0 -> 2638 bytes .../mipmap-xxhdpi/ic_launcher_foreground.webp | Bin 0 -> 3258 bytes .../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 0 -> 6360 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 0 -> 3522 bytes .../ic_launcher_foreground.webp | Bin 0 -> 3396 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 0 -> 8748 bytes app/src/main/res/values/colors.xml | 10 + .../res/values/ic_launcher_background.xml | 4 + app/src/main/res/values/strings.xml | 3 + app/src/main/res/values/themes.xml | 5 + app/src/main/res/xml/backup_rules.xml | 13 + .../main/res/xml/data_extraction_rules.xml | 19 + .../manalejandro/location/ExampleUnitTest.kt | 17 + build.gradle.kts | 6 + gradle.properties | 23 ++ gradle/libs.versions.toml | 32 ++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 185 ++++++++++ gradlew.bat | 89 +++++ settings.gradle.kts | 23 ++ 56 files changed, 1648 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/AndroidProjectSystem.xml create mode 100644 .idea/compiler.xml create mode 100644 .idea/deploymentTargetSelector.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/migrations.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 .idea/vcs.xml create mode 100644 README.md create mode 100644 app/.gitignore create mode 100644 app/build.gradle.kts create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/com/manalejandro/location/ExampleInstrumentedTest.kt create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/ic_launcher-playstore.png create mode 100644 app/src/main/java/com/manalejandro/location/LocationService.kt create mode 100644 app/src/main/java/com/manalejandro/location/LocationViewModel.kt create mode 100644 app/src/main/java/com/manalejandro/location/MainActivity.kt create mode 100644 app/src/main/java/com/manalejandro/location/ui/theme/Color.kt create mode 100644 app/src/main/java/com/manalejandro/location/ui/theme/Theme.kt create mode 100644 app/src/main/java/com/manalejandro/location/ui/theme/Type.kt create mode 100644 app/src/main/res/images/location.png create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.webp create mode 100644 app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/ic_launcher_background.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/themes.xml create mode 100644 app/src/main/res/xml/backup_rules.xml create mode 100644 app/src/main/res/xml/data_extraction_rules.xml create mode 100644 app/src/test/java/com/manalejandro/location/ExampleUnitTest.kt create mode 100644 build.gradle.kts create mode 100644 gradle.properties create mode 100644 gradle/libs.versions.toml create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle.kts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..23732d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties +.kotlin diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml new file mode 100644 index 0000000..4a53bee --- /dev/null +++ b/.idea/AndroidProjectSystem.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..b86273d --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 0000000..b268ef3 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..639c779 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 0000000..f8051a6 --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..74dd639 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..16660f1 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7b06619 --- /dev/null +++ b/README.md @@ -0,0 +1,200 @@ +# Location Simulator Android App 📍 + +Una aplicación Android desarrollada en Kotlin que simula la funcionalidad de ubicaciones de Google **sin necesidad de permisos reales de ubicación**. Perfecta para desarrollo, testing y demostraciones. + +## 🎯 Características + +- ✅ **Sin permisos de ubicación**: Simula ubicaciones sin acceso real al GPS +- 🗺️ **Última ubicación de Google**: Consulta y muestra la última posición guardada por Google (simulada) +- 🎲 **Ubicaciones aleatorias**: Genera posiciones aleatorias cerca de ciudades populares +- 🌍 **Ubicaciones populares**: Lista predefinida de ciudades importantes +- 📍 **Ubicación personalizada**: Permite ingresar coordenadas específicas +- 💾 **Persistencia**: Guarda la última ubicación simulada + +## 🏗️ Tecnologías + +- **Kotlin** - Lenguaje principal +- **Jetpack Compose** - UI moderna y declarativa +- **Material 3** - Diseño y componentes +- **Architecture Components** - ViewModel, StateFlow +- **SharedPreferences** - Almacenamiento local +- **Coroutines** - Programación asíncrona + +## 📱 Funcionalidades + +### 1. Ubicación Simulada +- **Última de Google**: Obtiene la última ubicación que Google tendría guardada +- **Simular Nueva**: Genera una nueva ubicación actual simulada +- Muestra coordenadas, precisión y timestamp + +### 2. Ubicaciones Populares +Ciudades predefinidas disponibles: +- 🇪🇸 Madrid, España +- 🇫🇷 París, Francia +- 🇬🇧 Londres, Reino Unido +- 🇺🇸 Nueva York, Estados Unidos +- 🇯🇵 Tokio, Japón +- 🇧🇷 São Paulo, Brasil +- 🇦🇺 Sídney, Australia + +Cada ciudad permite: +- Ir directamente a esa ubicación +- Generar una posición aleatoria cercana (radio de 1km) + +### 3. Ubicación Personalizada +- Ingreso manual de latitud y longitud +- Validación de coordenadas +- Guardado automático de la nueva posición + +## 🚀 Instalación y Configuración + +### Prerrequisitos +- Android Studio Arctic Fox o superior +- SDK mínimo: API 24 (Android 7.0) +- SDK objetivo: API 36 + +### Clonar e Instalar + +```bash +# Clonar el repositorio +git clone https://git.manalejandro.com/ale/location.git +cd location + +# Abrir en Android Studio +# File -> Open -> Seleccionar carpeta del proyecto + +# Sincronizar dependencias +# Build -> Make Project +``` + +### Configuración +No se requiere configuración adicional. La app funciona inmediatamente sin permisos especiales. + +## 🎮 Uso + +1. **Consultar última ubicación**: + - Toca "Última de Google" para obtener la posición guardada + - La app simula una consulta a los servicios de Google + +2. **Generar nueva ubicación**: + - Toca "Simular Nueva" para crear una ubicación actual + +3. **Usar ubicaciones populares**: + - Selecciona una ciudad para ir directamente + - Usa "Aleatorio" para generar posiciones cercanas + +4. **Ubicación personalizada**: + - Ingresa latitud y longitud manualmente + - Toca "Simular Ubicación" para aplicar + +## 📂 Estructura del Proyecto + +``` +app/src/main/java/com/manalejandro/location/ +├── MainActivity.kt # Actividad principal y UI +├── LocationViewModel.kt # Lógica de negocio y estado +├── LocationService.kt # Servicios de ubicación simulados +└── ui/theme/ # Tema y estilos Material 3 + ├── Color.kt + ├── Theme.kt + └── Type.kt +``` + +## 🔧 Arquitectura + +La aplicación sigue el patrón **MVVM (Model-View-ViewModel)**: + +- **View (Compose)**: Interfaz de usuario declarativa +- **ViewModel**: Manejo de estado y lógica de presentación +- **Model (LocationService)**: Simulación de servicios de ubicación + +### Flujo de Datos +``` +UI (Compose) ↔ ViewModel ↔ LocationService ↔ SharedPreferences +``` + +## 🎨 Diseño + +- **Material 3 Design**: Componentes modernos y accesibles +- **Responsive**: Adaptable a diferentes tamaños de pantalla +- **Dark/Light Theme**: Soporte automático según configuración del sistema +- **Cards y Sections**: Organización clara de funcionalidades + +## 🧪 Testing + +La aplicación incluye pruebas básicas: + +```bash +# Ejecutar tests unitarios +./gradlew test + +# Ejecutar tests instrumentados +./gradlew connectedAndroidTest +``` + +## 🤝 Contribuir + +1. Fork el proyecto +2. Crea una rama para tu feature (`git checkout -b feature/AmazingFeature`) +3. Commit tus cambios (`git commit -m 'Add some AmazingFeature'`) +4. Push a la rama (`git push origin feature/AmazingFeature`) +5. Abre un Pull Request + +## 📝 Casos de Uso + +### Para Desarrolladores +- Testing de aplicaciones que requieren ubicación +- Desarrollo sin depender de ubicación real +- Demostraciones en entornos controlados + +### Para QA/Testing +- Verificar comportamiento con diferentes ubicaciones +- Probar funcionalidades geográficas +- Testing sin moverse físicamente + +### Para Educación +- Enseñar conceptos de geolocalización +- Demostrar APIs de ubicación +- Workshops y tutoriales + +## 🔒 Privacidad + +Esta aplicación **NO**: +- Accede a tu ubicación real +- Requiere permisos de ubicación +- Envía datos a servidores externos +- Almacena información personal + +Toda la funcionalidad es local y simulada. + +## 📄 Licencia + +Este proyecto está bajo la Licencia MIT. Ver el archivo `LICENSE` para más detalles. + +## 👨‍💻 Autor + +**Manuel Alejandro** +- Git: [@manalejandro](https://git.manalejandro.com/ale) + +## 🙏 Agradecimientos + +- Equipo de Android Developers +- Comunidad de Kotlin +- Material Design Team + +--- + +⭐ Si este proyecto te ha sido útil, ¡no olvides darle una estrella! + +## 📸 Screenshots + +> Agrega capturas de pantalla de tu aplicación aquí + +## 🔄 Changelog + +### v1.0.0 +- Lanzamiento inicial +- Simulación de ubicaciones de Google +- Ubicaciones populares predefinidas +- Ubicaciones personalizadas +- UI con Material 3 diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..241efe4 --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,65 @@ +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.kotlin.compose) +} + +android { + namespace = "com.manalejandro.location" + compileSdk = 36 + + defaultConfig { + applicationId = "com.manalejandro.location" + minSdk = 24 + targetSdk = 36 + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } + buildFeatures { + compose = true + } +} + +dependencies { + + implementation(libs.androidx.core.ktx) + implementation(libs.androidx.lifecycle.runtime.ktx) + implementation(libs.androidx.activity.compose) + implementation(platform(libs.androidx.compose.bom)) + implementation(libs.androidx.ui) + implementation(libs.androidx.ui.graphics) + implementation(libs.androidx.ui.tooling.preview) + implementation(libs.androidx.material3) + + + // ViewModel y LiveData + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0") + implementation("androidx.compose.runtime:runtime-livedata:1.5.4") + + testImplementation(libs.junit) + androidTestImplementation(libs.androidx.junit) + androidTestImplementation(libs.androidx.espresso.core) + androidTestImplementation(platform(libs.androidx.compose.bom)) + androidTestImplementation(libs.androidx.ui.test.junit4) + debugImplementation(libs.androidx.ui.tooling) + debugImplementation(libs.androidx.ui.test.manifest) +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/androidTest/java/com/manalejandro/location/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/manalejandro/location/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..7ed3cfe --- /dev/null +++ b/app/src/androidTest/java/com/manalejandro/location/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.manalejandro.location + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("com.manalejandro.location", appContext.packageName) + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..80ca8c9 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..83b83f758358863788e55a7c8c86d929b72a9024 GIT binary patch literal 12589 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 literal 0 HcmV?d00001 diff --git a/app/src/main/java/com/manalejandro/location/LocationService.kt b/app/src/main/java/com/manalejandro/location/LocationService.kt new file mode 100644 index 0000000..25cc0f5 --- /dev/null +++ b/app/src/main/java/com/manalejandro/location/LocationService.kt @@ -0,0 +1,138 @@ +package com.manalejandro.location + +import android.content.Context +import android.location.Location +import kotlinx.coroutines.delay + +class LocationService(private val context: Context) { + + /** + * Simula obtener la última ubicación conocida que Google tendría guardada + * Devuelve una ubicación predeterminada o la última simulada + */ + suspend fun getLastKnownLocation(): Location? { + // Simular un pequeño delay como si fuera una consulta real a Google + delay(1000) + + // Primero intentar obtener la ubicación simulada guardada + val mockedLocation = getMockedLocation() + if (mockedLocation != null) { + // Actualizar el timestamp para simular que Google la tiene guardada + return mockedLocation.apply { + time = System.currentTimeMillis() - (1000 * 60 * 30) // 30 minutos atrás + } + } + + // Si no hay ubicación simulada, devolver una ubicación predeterminada que Google tendría guardada (Madrid) + return Location("google_provider").apply { + latitude = 40.4168 + longitude = -3.7038 + time = System.currentTimeMillis() - (1000 * 60 * 60 * 2) // 2 horas atrás + accuracy = 15.0f // Menos precisión para simular que es una ubicación guardada + } + } + + /** + * Simula obtener la ubicación actual de Google + */ + suspend fun getCurrentLocation(): Location? { + // Simular un delay más largo como si fuera una consulta GPS real + delay(2000) + + return getLastKnownLocation() + } + + /** + * Guarda una ubicación simulada + */ + suspend fun mockLocation(latitude: Double, longitude: Double): Boolean { + return try { + val preferences = context.getSharedPreferences("mock_location", Context.MODE_PRIVATE) + preferences.edit() + .putString("latitude", latitude.toString()) + .putString("longitude", longitude.toString()) + .putLong("timestamp", System.currentTimeMillis()) + .apply() + + // Simular un pequeño delay + delay(500) + true + } catch (e: Exception) { + false + } + } + + /** + * Obtiene la ubicación simulada guardada + */ + fun getMockedLocation(): Location? { + val preferences = context.getSharedPreferences("mock_location", Context.MODE_PRIVATE) + val latStr = preferences.getString("latitude", null) + val lngStr = preferences.getString("longitude", null) + + return if (latStr != null && lngStr != null) { + Location("mock_provider").apply { + latitude = latStr.toDouble() + longitude = lngStr.toDouble() + time = preferences.getLong("timestamp", System.currentTimeMillis()) + accuracy = 5.0f // Simular buena precisión + } + } else null + } + + /** + * Genera ubicaciones aleatorias cercanas a una ubicación base + */ + fun generateRandomNearbyLocation(baseLatitude: Double, baseLongitude: Double, radiusKm: Double = 1.0): Location { + val random = kotlin.random.Random + + // Generar offset aleatorio dentro del radio especificado + val offsetLat = (random.nextDouble() - 0.5) * 2 * (radiusKm / 111.0) // 1 grado lat ≈ 111 km + val offsetLng = (random.nextDouble() - 0.5) * 2 * (radiusKm / (111.0 * kotlin.math.cos(Math.toRadians(baseLatitude)))) + + return Location("random_provider").apply { + latitude = baseLatitude + offsetLat + longitude = baseLongitude + offsetLng + time = System.currentTimeMillis() + accuracy = random.nextFloat() * 20 + 5 // Precisión entre 5-25 metros + } + } + + /** + * Obtiene ubicaciones predefinidas populares en España + */ + fun getPopularLocations(): List> { + return listOf( + "Madrid" to Location("predefined").apply { + latitude = 40.4168 + longitude = -3.7038 + time = System.currentTimeMillis() + accuracy = 10.0f + }, + "Barcelona" to Location("predefined").apply { + latitude = 41.3851 + longitude = 2.1734 + time = System.currentTimeMillis() + accuracy = 10.0f + }, + "Valencia" to Location("predefined").apply { + latitude = 39.4699 + longitude = -0.3763 + time = System.currentTimeMillis() + accuracy = 10.0f + }, + "Sevilla" to Location("predefined").apply { + latitude = 37.3886 + longitude = -5.9823 + time = System.currentTimeMillis() + accuracy = 10.0f + }, + "Bilbao" to Location("predefined").apply { + latitude = 43.2627 + longitude = -2.9253 + time = System.currentTimeMillis() + accuracy = 10.0f + } + ) + } +} diff --git a/app/src/main/java/com/manalejandro/location/LocationViewModel.kt b/app/src/main/java/com/manalejandro/location/LocationViewModel.kt new file mode 100644 index 0000000..c138e60 --- /dev/null +++ b/app/src/main/java/com/manalejandro/location/LocationViewModel.kt @@ -0,0 +1,176 @@ +package com.manalejandro.location + +import android.location.Location +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +data class LocationState( + val currentLocation: Location? = null, + val mockedLocation: Location? = null, + val popularLocations: List> = emptyList(), + val isLoading: Boolean = false, + val error: String? = null, + val hasLocationPermission: Boolean = true // Siempre true ya que no necesitamos permisos +) + +class LocationViewModel(private val locationService: LocationService) : ViewModel() { + + private val _uiState = MutableStateFlow(LocationState()) + val uiState: StateFlow = _uiState.asStateFlow() + + init { + loadMockedLocation() + loadPopularLocations() + } + + /** + * Carga la ubicación simulada guardada + */ + private fun loadMockedLocation() { + val mockedLocation = locationService.getMockedLocation() + _uiState.value = _uiState.value.copy(mockedLocation = mockedLocation) + } + + /** + * Carga las ubicaciones populares predefinidas + */ + private fun loadPopularLocations() { + val popularLocations = locationService.getPopularLocations() + _uiState.value = _uiState.value.copy(popularLocations = popularLocations) + } + + /** + * Obtiene la última ubicación conocida (simulada) + */ + fun getLastKnownLocation() { + viewModelScope.launch { + _uiState.value = _uiState.value.copy(isLoading = true, error = null) + + try { + val location = locationService.getLastKnownLocation() + _uiState.value = _uiState.value.copy( + currentLocation = location, + isLoading = false, + error = if (location == null) "No se encontró ubicación guardada" else null + ) + } catch (e: Exception) { + _uiState.value = _uiState.value.copy( + isLoading = false, + error = "Error al obtener ubicación: ${e.message}" + ) + } + } + } + + /** + * Obtiene la ubicación actual (simulada) + */ + fun getCurrentLocation() { + viewModelScope.launch { + _uiState.value = _uiState.value.copy(isLoading = true, error = null) + + try { + val location = locationService.getCurrentLocation() + _uiState.value = _uiState.value.copy( + currentLocation = location, + isLoading = false, + error = if (location == null) "No se pudo obtener ubicación actual" else null + ) + } catch (e: Exception) { + _uiState.value = _uiState.value.copy( + isLoading = false, + error = "Error al obtener ubicación actual: ${e.message}" + ) + } + } + } + + /** + * Simula una nueva ubicación + */ + fun mockLocation(latitude: Double, longitude: Double) { + viewModelScope.launch { + _uiState.value = _uiState.value.copy(isLoading = true, error = null) + + try { + val success = locationService.mockLocation(latitude, longitude) + if (success) { + val mockedLocation = locationService.getMockedLocation() + _uiState.value = _uiState.value.copy( + mockedLocation = mockedLocation, + isLoading = false, + error = null + ) + } else { + _uiState.value = _uiState.value.copy( + isLoading = false, + error = "Error al simular ubicación" + ) + } + } catch (e: Exception) { + _uiState.value = _uiState.value.copy( + isLoading = false, + error = "Error al simular ubicación: ${e.message}" + ) + } + } + } + + /** + * Establece una ubicación predefinida + */ + fun setPopularLocation(location: Location) { + mockLocation(location.latitude, location.longitude) + } + + /** + * Genera una ubicación aleatoria cerca de una ubicación base + */ + fun generateRandomLocation(baseLocation: Location) { + viewModelScope.launch { + _uiState.value = _uiState.value.copy(isLoading = true, error = null) + + try { + val randomLocation = locationService.generateRandomNearbyLocation( + baseLocation.latitude, + baseLocation.longitude, + 2.0 // Radio de 2 km + ) + + val success = locationService.mockLocation(randomLocation.latitude, randomLocation.longitude) + if (success) { + val mockedLocation = locationService.getMockedLocation() + _uiState.value = _uiState.value.copy( + mockedLocation = mockedLocation, + currentLocation = randomLocation, + isLoading = false, + error = null + ) + } + } catch (e: Exception) { + _uiState.value = _uiState.value.copy( + isLoading = false, + error = "Error al generar ubicación aleatoria: ${e.message}" + ) + } + } + } + + /** + * Actualiza el estado de permisos (ya no necesario) + */ + fun updatePermissionStatus(hasPermission: Boolean) { + // No hacemos nada ya que no necesitamos permisos + } + + /** + * Limpia errores + */ + fun clearError() { + _uiState.value = _uiState.value.copy(error = null) + } +} diff --git a/app/src/main/java/com/manalejandro/location/MainActivity.kt b/app/src/main/java/com/manalejandro/location/MainActivity.kt new file mode 100644 index 0000000..2ef45aa --- /dev/null +++ b/app/src/main/java/com/manalejandro/location/MainActivity.kt @@ -0,0 +1,344 @@ +package com.manalejandro.location + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.manalejandro.location.ui.theme.LocationTheme +import java.text.SimpleDateFormat +import java.util.* + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + setContent { + LocationTheme { + LocationApp() + } + } + } +} + +@Composable +fun LocationApp() { + val context = LocalContext.current + val locationService = remember { LocationService(context) } + val viewModel: LocationViewModel = viewModel { LocationViewModel(locationService) } + + val uiState by viewModel.uiState.collectAsState() + + Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(innerPadding) + .padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + // Título + Text( + text = "Simulador de Ubicación", + fontSize = 24.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + + Text( + text = "Esta aplicación simula ubicaciones sin necesidad de permisos reales", + fontSize = 14.sp, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + + // Sección de ubicación actual/simulada + CurrentLocationSection( + uiState = uiState, + onGetLastLocation = viewModel::getLastKnownLocation, + onGetCurrentLocation = viewModel::getCurrentLocation + ) + + // Sección de ubicaciones populares + PopularLocationsSection( + uiState = uiState, + onSelectLocation = viewModel::setPopularLocation, + onGenerateRandom = viewModel::generateRandomLocation + ) + + HorizontalDivider() + + // Sección para simular ubicación personalizada + CustomLocationSection( + uiState = uiState, + onMockLocation = viewModel::mockLocation + ) + + // Mostrar errores + uiState.error?.let { error -> + ErrorSection( + error = error, + onDismiss = viewModel::clearError + ) + } + } + } +} + +@Composable +fun CurrentLocationSection( + uiState: LocationState, + onGetLastLocation: () -> Unit, + onGetCurrentLocation: () -> Unit +) { + Card(modifier = Modifier.fillMaxWidth()) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = "Ubicación Simulada", + fontSize = 18.sp, + fontWeight = FontWeight.Bold + ) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Button( + onClick = onGetLastLocation, + enabled = !uiState.isLoading, + modifier = Modifier.weight(1f) + ) { + Text("Última de Google") + } + + Button( + onClick = onGetCurrentLocation, + enabled = !uiState.isLoading, + modifier = Modifier.weight(1f) + ) { + Text("Simular Nueva") + } + } + + if (uiState.isLoading) { + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center + ) { + CircularProgressIndicator() + } + } + + uiState.currentLocation?.let { location -> + LocationDisplay( + title = if (location.provider == "google_provider") + "Última ubicación guardada por Google" + else + "Ubicación Actual", + location = location + ) + } + } + } +} + +@Composable +fun PopularLocationsSection( + uiState: LocationState, + onSelectLocation: (android.location.Location) -> Unit, + onGenerateRandom: (android.location.Location) -> Unit +) { + Card(modifier = Modifier.fillMaxWidth()) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = "Ubicaciones Populares", + fontSize = 18.sp, + fontWeight = FontWeight.Bold + ) + + LazyRow( + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + items(uiState.popularLocations) { (cityName, location) -> + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Button( + onClick = { onSelectLocation(location) }, + enabled = !uiState.isLoading + ) { + Text(cityName) + } + + OutlinedButton( + onClick = { onGenerateRandom(location) }, + enabled = !uiState.isLoading, + modifier = Modifier.width(100.dp) + ) { + Text("Aleatorio", fontSize = 10.sp) + } + } + } + } + + if (uiState.popularLocations.isNotEmpty()) { + Text( + text = "Toca una ciudad para ir allí, o 'Aleatorio' para generar una ubicación cercana", + fontSize = 12.sp, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } + } +} + +@Composable +fun CustomLocationSection( + uiState: LocationState, + onMockLocation: (Double, Double) -> Unit +) { + var latitude by remember { mutableStateOf("") } + var longitude by remember { mutableStateOf("") } + + Card(modifier = Modifier.fillMaxWidth()) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + Text( + text = "Ubicación Personalizada", + fontSize = 18.sp, + fontWeight = FontWeight.Bold + ) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + OutlinedTextField( + value = latitude, + onValueChange = { latitude = it }, + label = { Text("Latitud") }, + placeholder = { Text("40.4168") }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal), + modifier = Modifier.weight(1f) + ) + + OutlinedTextField( + value = longitude, + onValueChange = { longitude = it }, + label = { Text("Longitud") }, + placeholder = { Text("-3.7038") }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Decimal), + modifier = Modifier.weight(1f) + ) + } + + Button( + onClick = { + val lat = latitude.toDoubleOrNull() + val lng = longitude.toDoubleOrNull() + if (lat != null && lng != null) { + onMockLocation(lat, lng) + } + }, + enabled = latitude.isNotBlank() && longitude.isNotBlank() && !uiState.isLoading, + modifier = Modifier.fillMaxWidth() + ) { + Text("Establecer Ubicación Personalizada") + } + + uiState.mockedLocation?.let { location -> + LocationDisplay( + title = "Ubicación Guardada", + location = location + ) + } + } + } +} + +@Composable +fun LocationDisplay(title: String, location: android.location.Location) { + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.secondaryContainer) + ) { + Column( + modifier = Modifier.padding(12.dp), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + Text( + text = title, + fontWeight = FontWeight.Medium, + color = MaterialTheme.colorScheme.onSecondaryContainer + ) + Text( + text = "Latitud: ${String.format("%.6f", location.latitude)}", + color = MaterialTheme.colorScheme.onSecondaryContainer + ) + Text( + text = "Longitud: ${String.format("%.6f", location.longitude)}", + color = MaterialTheme.colorScheme.onSecondaryContainer + ) + if (location.hasAccuracy()) { + Text( + text = "Precisión: ${String.format("%.1f", location.accuracy)} metros", + color = MaterialTheme.colorScheme.onSecondaryContainer + ) + } + Text( + text = "Hora: ${SimpleDateFormat("dd/MM/yyyy HH:mm:ss", Locale.getDefault()).format(Date(location.time))}", + color = MaterialTheme.colorScheme.onSecondaryContainer + ) + } + } +} + +@Composable +fun ErrorSection(error: String, onDismiss: () -> Unit) { + Card( + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.errorContainer) + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + text = error, + color = MaterialTheme.colorScheme.onErrorContainer, + modifier = Modifier.weight(1f) + ) + TextButton(onClick = onDismiss) { + Text( + text = "Cerrar", + color = MaterialTheme.colorScheme.onErrorContainer + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/manalejandro/location/ui/theme/Color.kt b/app/src/main/java/com/manalejandro/location/ui/theme/Color.kt new file mode 100644 index 0000000..41a8955 --- /dev/null +++ b/app/src/main/java/com/manalejandro/location/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.manalejandro.location.ui.theme + +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) \ No newline at end of file diff --git a/app/src/main/java/com/manalejandro/location/ui/theme/Theme.kt b/app/src/main/java/com/manalejandro/location/ui/theme/Theme.kt new file mode 100644 index 0000000..db0ae33 --- /dev/null +++ b/app/src/main/java/com/manalejandro/location/ui/theme/Theme.kt @@ -0,0 +1,58 @@ +package com.manalejandro.location.ui.theme + +import android.app.Activity +import android.os.Build +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.dynamicDarkColorScheme +import androidx.compose.material3.dynamicLightColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext + +private val DarkColorScheme = darkColorScheme( + primary = Purple80, + secondary = PurpleGrey80, + tertiary = Pink80 +) + +private val LightColorScheme = lightColorScheme( + primary = Purple40, + secondary = PurpleGrey40, + tertiary = Pink40 + + /* Other default colors to override + background = Color(0xFFFFFBFE), + surface = Color(0xFFFFFBFE), + onPrimary = Color.White, + onSecondary = Color.White, + onTertiary = Color.White, + onBackground = Color(0xFF1C1B1F), + onSurface = Color(0xFF1C1B1F), + */ +) + +@Composable +fun LocationTheme( + darkTheme: Boolean = isSystemInDarkTheme(), + // Dynamic color is available on Android 12+ + dynamicColor: Boolean = true, + content: @Composable () -> Unit +) { + val colorScheme = when { + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + + darkTheme -> DarkColorScheme + else -> LightColorScheme + } + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/manalejandro/location/ui/theme/Type.kt b/app/src/main/java/com/manalejandro/location/ui/theme/Type.kt new file mode 100644 index 0000000..9ecdbe6 --- /dev/null +++ b/app/src/main/java/com/manalejandro/location/ui/theme/Type.kt @@ -0,0 +1,34 @@ +package com.manalejandro.location.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) + /* Other default text styles to override + titleLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp + ), + labelSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp + ) + */ +) \ No newline at end of file diff --git a/app/src/main/res/images/location.png b/app/src/main/res/images/location.png new file mode 100644 index 0000000000000000000000000000000000000000..9d077b13e60469d2893ccaaf0f927f16842e2cbf GIT binary patch literal 1471 zcmV;w1wi_VP)1^@s6-S$}h000GsNkl(@X{a>Ly{_FuN{?6sETnSr~cL;orZ%yl9&M6jTYJXVbNJ^&w=L2eg9;;{q!pnm&BWZOI7smAHUdE`B=DNp#IZ`es{7eeBh z;mm+0vBYcb9!F>i(0A-7wF@EfT=U)qu3m|3M~fG}rz3FwIuN$@V;L*gfj`@e+zy1q z(=tXxZpBR8T{}W;*S2xxLCihQ-1DqrOr8Zk;Vp7I5E9Qdekg52Rp9BF`oEVdp`zQ+ zD{9HDz+ZR?#-fJTS-TJ)&qQI+d`XeJ4Cc|m1NEpctBRZ?9v8gd^DvgJCbxt5#1nw| zz`)2{Ms5dU;=MB#sHr9wfiZId_~`NEb|5C+qItmiTyhcU-*315DT|PJ%El}xySJ0u zPFpYZt$RrALP$L1=fU;q98%kPvJ3RA&7^iACZ2hP^6~p%g%`=~#8~wmc=sOUb|EaD za`<;BtCo`6Mrs=Lb=jnLA}k&_hq7`hl%oe|^tfS~hI?6C!2I@}DE>oSJd?YXP#4Yw zyVc64B~b{!IR)WK)5+~dY&?^aE6_4$g9igNdK~bfBVjD~j9dibJ_*$=YR+5 zXl8}*xD14+&H~g2@0aZ)F7YCmhw$pB0V(4x z+4(CD<` zQpP(`bOT2UO31x!5-|Oh{^YVCWxPve<=B&Z|G!(b^SUu*NI!B}kTPCPD1;4%a>)J3 ziI_O3H@PfG8P8B{9(U%A#J=v7mJZod=oBJ!5j%MQ%t0dce>;z{`k9C+RGFZY2#fg ztH7Sz0(409;O)VEX)Y7e#=B8jgB{27klHR083X0JOfiu*o=MT|N_0$W8##1kMCy35 Z^DmWs_$^KjuA~3}002ovPDHLkV1nY3*jfMp literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..d52f15ca176f62de562b22330d8cfab18ef8f248 GIT binary patch literal 1386 zcmV-w1(o_zNk&Fu1pok7MM6+kP&iCg1pojqN5Byf)dqsLZ4>jSz3qn(5fjiEwmum0 zScR@|Bmh#R^o!7l>>}h>#Jqyo9WrNsd&f z>=*8T{!vcVAZXjRseDQAw$`>aIdS*kv{b%q~E-$LZdc`l>mszvFF652iIY+ySw2ua9!jz5Yu=hN9Jfo}UYeAAxR~q-D6_1^Z`0g&ak6u{-WeoT<-io;Irg1;(c|~S4a2OGQ5>+ zf0WW@mb-or=%z{F2sk7g-0AyY2Xyl|h-(jI69kmn{=pCKEC7pGACDw2>v35?ZGL zx&ne&0Os&;CVEe+pB+KgQj&s!zJJ$~lgot5teGx`iFq6Vmq1v=z$i^s{w1D&sf#;x z{mCv+VVtHu3cxLZ4R>^CFOOK%!SjXui1x+q>V zS*xaa{V@HJP@(0j*t4M}5>@P~Gq`LCD?>;HIczvfRJHA_D+6*m6y z%t^yvxvbXykO~{FsQIdB+R)wi`KAkRoW8bn;tqdz;4y>iP*Vq;fwpo&HuRj`dPeT+ zx~`5oy*Bk59N2Q<{CCoFQ_g+Hr*N{mH1JJpb`f`$z_w)P2AM zBmqh(T_;TFqzOR8 sf(Q@?$N*#ka_FBA0Adj!0T4PwvB3C1j|DpdqUbNSPRQ1018FT40E@Q4-v9sr literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..1685ca6c0d107b41cbacc8851a0fb0cafe90612e GIT binary patch literal 1892 zcmV-q2b=g(Nk&Fo2LJ$9MM6+kP&iCb2LJ#sp+G1QB0Af)o3@=FXWO=|W81cE+qP}{ zEN%RRg*n&UYm9?9X>Hr)DpT3Et@>24J&G?Ju~XTpY*jk8PZc}4C<_jMd(FhfG+|tEzDfeUlsHF|NU3OAC|T!oe>y{ zGL{H3rnT9M`MvZ!l7f2^a$6vmdUCESXZF}*4|mQA<*NAHl!AM*@^mGC)!y8AanNWq z`&hCStoi(EfR#VZ^3&J}g_EqI!VnkD*snl+q$>Wzh z!_UtcEEtGfb2H`jE7k!qiBgNQ#4ASv5*}JmVf8Vo!3F7^Q0)NB6(dAbkPjCWv%9Tf z^%<`zG`} z1`B1m-B9viF7E)(bBG&>S{t(`_H8Co7?fa#s_MLj3`6UbZiLjtl}0oKm{MKHZnl9P zaosFb(jOA-2v}8Q3z@=sI}n-Q&g~bGb`US4)A&J4>Nj+&X(uz9{H|u;%Qn}AQ)TSQ zY=rSaH?{vkT&^$iHeZJn6qCvBxz3~{+E6xPDpg!=7=*$>=o*1)Ezn-N)kk*aB*wFIk) zrx&4{K(@&qx!$NGT$c@BE-c{>kk!hp`TPnY(-+GA#u`r&R#(sJr;t_2U&Y~iMrV2E z`ssvS4T0(WFtQ5yEmuu5InOtt`Vl^irMU^YwU@|0jbCz6o`%s^=26 z?`&-UBG5xrIv&;t03qAB<=XRPaHuMuC#-vLZehD41dFINJTRA#4Rr!|;CYh3x+2q$ z@P_Q!5KF}Ee9(wW?FR@UWJ9a6%(>Ou%R>ic zWJBEuZseM4y>lcW;qJNa=;w(%&7=wD3bYYbaprEQ7P#wfIQJvDoDiRz|3XxHKcXp6 z0wQAPcZhh}ppv2VZfAVht$2WO6XVLGZB*slzJ zlrx89_7jwo3aKB`FLLID+Ad3z`F)lYAzzOBkk1RpgShQ>V z7Z1+ngpLHZ!unf=qU*=Ia`-uS&gOu6;QMh=bC~u-7(J-2eLq%5LZ#g7L_9MhtNn;F zItHy~X0RfnDNt_7eRp;HK)I@@4w~H-4tLGc44{18IkdC+1z-_JMd%GfxuD+&(<%*t zbLC(|EH>BG@Q=e$rKqEHfThd&6a64jvZvgmls~-oAPk_tev*XS?Mbn8yQ$P=>`6bQ zD3=x4k2f~4f5rT6GT*hDu0)Jf#rwyb^Is_8_dl4836vgmT|N6A&Na@OGM3`^y>FMI zyj@d}p2TO`kzDm^yNH)N)#N6hmMYbZ;129*Dq2zWV{k1rcU21H9MxstR zulS}9L8*he&#u$>J^sc6UaM9+Enl?HK2A#)IW1aJ<=^{9&hCN8P?UDX5Al&dTDhh? zPB7|3(8%4l-4--_Pw?PbEDBdHvqg+cbnr?jEU+V@*A0^hr9q#ZI!A1E*Gzn#TZJP zAM*o1%?;MpXCs1^F4nX@6Rx_-1W;$Iz3bhKu&swR?JmZ?2KaaVld-1DtyF_uE`Y}S zJ)?fKBfExJ)AMnz*%2R9UiyDaQF}is8(~e~m&I16LQrM7q1CA%jj5;@_@UbVQVgoC zHn%w&!JMI=8l7*YpymckyGv2b8S$;v?S2MoZ?<)~62qL)zv*62^H6u2z0>ss=KRWU eV!s&vrFjqL(1^~#=wF?wo8eB3=G;pDUmitH9kcrY literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..1c7de517f821196f86c1631c4efa28dc75cbc051 GIT binary patch literal 3000 zcmV;p3rF-)Nk&Gn3jhFDMM6+kP&iDa3jhEwN5ByfRfmGMZ5W3?>>UgdF#+Dy(nLEv z{2bnPqwQa9yZMXK8;O~jnVFfHDPm@3W~P{#nVI1-^WnAEx})^MK6~x8&u-u+2>BNY z8exVrw*pn5nNxxo@>77Q0!(q`QbzF&1^-N=RG~(ZQpTke+t4V(C5Y7nRY1{+SFBM3 z%9Q;@u_8sB?oeC<*sj42JuCD$)VP(u;gsM4T!c$l1>7Q>xdTTkVuhyIPMx~}j6{3J zu|pT24tDAyn4ykUfMbV(=t8F4a7vIENs=Tfet=-;F9}GnUq!A2w~Zu8;-r-|_ss78 z|Emi~ux;D4qi@ExZQHhO+qRu9I4Rq;63faw`B(WTiKEcXxMpcXtil-QC^Y z-TnU>xZRnflp&@R?T?!1V)Cnslt&145dW44>B2Q9-bRpect57DUluWiQUV1K{Y`mq zQ>vm2dZHL&=m-h`00bM`wr$&Xb+c_F&9=S!k2dyb+qUg60MN9F)?32=&sFBW1nScN z2>@T`hpOg>7OSd)AFKJH=Z9f|Ov|uTziwqdz7N9h)_4&RX0Kr(^UdZ(@gyh&NW23 z;;H8VI98l60Hn)Js*h5E;v3vVuTB02B0b>;0EX`z2L!L`QuiUF$Td`0T?S3hC?E;0fP znNi!4ynf3HF@&yl5q|RnL!taIL1b^LI-#i!|Fj3>C=_zFSV&YP5rpz#$Wi9oX*Cs^zR1%4TKKCaxM5gZ zfoj1nkIxlnlV9F6tD+wBfSkq@vbF#MB~gL=Fd+JUjZQ<3a@VDFO8hEA531z*DMM%h zY52Q63tF5-iHS@2pTQGy8hyK1=6%f|KMb!Ni1JTFtOd$Z?v*m1T^YxUw1)+xWe88T zaaW$+zyi~}96iiMjQ_)g zeBI<+HLb`h5*Wf9?Ja@ojR7%LLPIF~O0&HXYG*0V+YHtcSb-ZI>{YPqk4efi?shRY1+DJ+>q2{Fci$xp4f5>2*2yXH1u-FKxm+P zEX{sjVDUhT{l9TBNhiTAnmFh zG=T;Ur8=s|&^3@lhm`;@S&p_lHcH^Q8IZS=L3IS4)KpH@BQ)BkaoiHu2+)iu%s+)- zxLI~&_Zj8h-TepcjYsM97KGz6^@c#R03bh9nBI?sQ0r)V_qWCF5alur=~YhnjzCS8 zWp{H>AM&6ASddZfR6_;lm6Sv6$lF73czVgId00?XK=}1zrdA-#1_Qu=992!Z5?5;6 zc5PTs!=RP%eZBLsFJ!>ph$_sxT5JQr3go>_q9W*aLeeVKPA~*IDI{ZFlhz2F2N!Gi z0~V+%fgZ7bDuh;K^_|yT{R||@#hMKJgVNe|y-KUIjZKA0RLOY^5GitSL8P8~ z(-A-C3^m0N+7&Tl+N#`VkM=*b1EgY@Pz)8S!6G?wEAu&STtTokmb0A={bu4e;ft5jU4PU-RiR9TBi1zPz8SnpBWA#57+r_ae-bx8Ejx6U zcAHCu1gNS?;OAbyko#upKFwUhI042BFns}czAQU9UF_R`f{3buMc`(+-S*YgU0S^E z@>Y;4T*IC3h%Ldn+oP{q0LFcbt|scE$=kGO&9Uo^?@h6K?lS-^0%H;dQuM1J%iS=X z#e9$gpaxp^rW&!<(DWyrrTN~CCcNqdQ~*dJh-Rvn$o+{2=U5*IVkrOs27x#0P6_J% zBo+y47=Np~YhjpfDuLOWM?a#r(DWajrE5Elx@KQf-C#mk1c}8xlgRz&jp)L3-#xr& zLx|P7YuJ~dB&zv~Py&{{&|8bTD}*!{|G`ulEQSWZMlOOwgEj zd!MwKQj5=V^$t)}$-09R6ze)^+WJh;ENRPw9}>hXz;u~5iy?*9UZaNnippQX@=bsf zq6=(u_=UBe^Dc6b6a))C{%Y=7FeE@ z1|)bkUAi6hGPw!$ArSy&15F@FP;WOO3$MA4zAF^*ZssAa+=j9ZSbRwkp#I$h=iixY zJ>fUU2SDjSGe{6rQ(-;h_9171Z6=h!o5km(cDJhBf|b{pT>NJ2vZ=rOlnR^Q9}ocL z?IsZ=C=!fD+e>%q+rfcsvv_%{Z*lzr)a+ENuQ8eU&Dep<+zv+C=_45b>q;AZY1aX- z666Uw4dFZ0&Z{him;!r4mlOVeu*m;UEcEXSVb2Rs`Wq~G(v-ctZV)T_rJF7Do4eoi0r=i7Tp6+n z1e4AzX_D>1Qk{*@Co{Iv8(fbmqU*Z8qt4%0iLvB74WIZ-r2_OEd2*lYUC2K_X9)d2x zxH6o(>tv158JuE0o@?jtA~lt|vzGqa%~Xdko}7AHTXc8oktx6T@mO~T|MFh(AMJib z$s!P^169J_?Vm;8CFng<2Igg8{a!uh(+K|CeD1w6usZgcPrY08pSyh{0C7K11FVuK u){IP9$URzg_uv11_o9#P@aq#xJ{$nQwF8a9r~_tmu&=n{>DzA$*x+OAdCUd? literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..e51a1219cf3f04b64be9bc389237b3a8281f4ce0 GIT binary patch literal 934 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 Ie;*m50TT+icK`qY literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..4a82ab10418d85fe9f507891f39b08c2c2bf5852 GIT binary patch literal 1916 zcmV-?2ZQ)hNk&F=2LJ$9MM6+kP&iCy2LJ#sU%(d-^@f7BZ5VI-VSfe@F#$yDFw5D! zI^Ll$%@O2k+kVc`cNVc#rgx6O&Jj2{gJv`*GWr5=@SoB!W`f_BOut5n~$wr$(2 zrkiS}+iO&ck{@Au{8)a4|V2ma! zW%|^qlF`_zY~%XA69Bcgt>sbKQPco4rvYYWW@cuFIo6P7=L8|wzIo&D|On@ify9`ZU6uTo7lFt+P1CDwr$0>ZPalN>FghRfFT9| zo3^nfcf9}K3v*JEWVZW10ocXb2x0^c@D~r84V7rKF*AZeG=lAXlMtVZc$Jdh+P)w0 zAtM`VFxsXMZLb)7EIYn41VD-@MLfE zG^yVWinMN+UEMq=_>0DdlRlJs9XF8r6F@tGb_VZ${2&`}yYY0v?9}{YLK_u;8tJj< z_2Bkx6lg|3*oDDO1!_@4eYd#2t|?Q^WEckHC=kD)TGXDkuJ<_|fDCo5y!bcUvvuxF zj6C$deCMDM3yWO5Xk!phu?su#IkWNJ*>7kT&UsYJXQBhpeLZ$g&v#_0wB_KU5JTU? z*uR^3RtxuH?pcfjo5tN;I!#nALFzZ;sFtLSu%SrtNEWtdnF0V>v@Q(J>L?x(Yv6yF zc^3!k;AZSRb*-1KedeKW9jv2nxXw&WB*jJqh(NtzZgI@ zBb>GzJ8;Njq6-6M!`Z+~dg0y0)ISx{-Zsi5Uo1eiLsT@LdXb2SF@RarP^^utd3!lo z`lmwPIVqERvw?J)O&q+qz79eS7OL4g^1v%UzD<3rx26%oOV`>uCe??Bbowm-M51>6$5kfmIdCQEkE4zdjY{rEL$X-9JEhYUGw0w#LBJzO3(KAr3oONA>$Vh^iIl z^~H4*Xt-B6krbl>dXdB3(6Rk|FA+)gj>?B}FA}+zxfm%ZM<15%`5EJ`abT58zCmQg zD93HbHX?8@V=+o)2qbFv_ZJ7;jJ>;|bFhtu!R-%-{@;)1ny4BJ0Dn&Ch4%|5i9Rl}){%KIPjyX2~ueYA$6ahDNp|%FaNtep8qpG zeuuscK`j;4CPCBJ7sto!Ydc)|6m+M)zP`9Vkkv0Cj*4W7Xo_Mu`9JgZ1!lc|ZfNx<{S8t-=KEth%Qyl6wFDd;fJ%b` zh>I;fcD7vBV8c@do?hNyRA-grDmI44k Cvb4?s literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..2878bf539cbac2d60b6de8a0e70151481871a1ef GIT binary patch literal 2678 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 0000000000000000000000000000000000000000..00609b50c0faa359e843354c82149be3cd995ba3 GIT binary patch literal 3258 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 sdaGh@+E4Zi{M(^`%o9!T2wT{|Ufj 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 ag~nJ0j|DRrjH;{wXaLXv7yuXmqoM&EUM!IS literal 0 HcmV?d00001 diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..e4403e9e56aa8e960dcc8837208d7356d68ef7f5 GIT binary patch literal 3522 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 z00 + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..10c1ef7 --- /dev/null +++ b/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #F0F3F7 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..a981fdb --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + location + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..7a8dce6 --- /dev/null +++ b/app/src/main/res/values/themes.xml @@ -0,0 +1,5 @@ + + + +