Añadir pantalla login y conexion a mariadb

This commit is contained in:
2026-07-13 13:02:27 +02:00
parent 6a02e05de5
commit f680750119
10 changed files with 214 additions and 18 deletions
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetSelector">
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DialogSelection />
</SelectionState>
</selectionStates>
</component>
</project>
+1
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="jbr-21" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">
+23 -15
View File
@@ -1,38 +1,46 @@
# Saludapp # Saludapp
Saludapp es una aplicación Android moderna enfocada en la salud y el bienestar, desarrollada utilizando las últimas tecnologías y prácticas recomendadas de Android. Saludapp es una aplicación Android moderna enfocada en la salud y el bienestar, diseñada para ser multiusuario y conectada a una base de datos externa.
## 🚀 Características ## 🚀 Características
- Interfaz de usuario moderna con **Jetpack Compose**. - **Sistema Multiusuario:** Autenticación de usuarios mediante Login.
- Pantalla de inicio atractiva con mensaje de bienvenida. - **Conexión a Base de Datos:** Integración directa con **MariaDB** autohospedado.
- Diseño basado en **Material 3** con soporte para temas dinámicos. - **Interfaz Moderna:** Desarrollada íntegramente con **Jetpack Compose**.
- Arquitectura limpia y escalable. - **Diseño Material 3:** Uso de componentes y temas dinámicos de última generación.
- **Navegación Fluida:** Flujo desde pantalla de inicio hasta el panel principal.
## 🛠️ Tecnologías utilizadas ## 🛠️ Tecnologías utilizadas
- **Lenguaje:** [Kotlin](https://kotlinlang.org/) - **Lenguaje:** [Kotlin](https://kotlinlang.org/)
- **UI Framework:** [Jetpack Compose](https://developer.android.com/jetpack/compose) - **UI Framework:** [Jetpack Compose](https://developer.android.com/jetpack/compose)
- **Base de Datos:** [MariaDB](https://mariadb.org/) (via MariaDB Java Client)
- **Asincronía:** Corrutinas de Kotlin para operaciones de red no bloqueantes.
- **Diseño:** [Material Design 3](https://m3.material.io/) - **Diseño:** [Material Design 3](https://m3.material.io/)
- **Gestión de dependencias:** Gradle (Kotlin DSL)
## 📋 Requisitos previos ## 📋 Requisitos previos
- Android Studio Ladybug o superior. - Android Studio Ladybug o superior.
- JDK 17 o superior. - JDK 17 o superior.
- SDK de Android (Nivel de API 24 o superior recomendado). - SDK de Android 37 (API level 37).
## 🔧 Configuración e Instalación ## 🔧 Configuración e Instalación
1. Clona este repositorio: 1. **Clonar el repositorio:**
```bash ```bash
git clone https://github.com/tu-usuario/Saludapp.git git clone https://github.com/tu-usuario/Saludapp.git
``` ```
2. Abre el proyecto en **Android Studio**. 2. **Configurar Credenciales:**
3. Sincroniza el proyecto con los archivos de Gradle. - Abre el archivo `app/src/main/java/com/example/saludapp/data/DatabaseHelper.kt`.
4. Ejecuta la aplicación en un emulador o dispositivo físico. - Sustituye `TU_CONTRASEÑA_AQUÍ` por la contraseña real de tu base de datos MariaDB.
3. **Sincronizar Gradle:** Abre el proyecto en Android Studio y espera a que termine la sincronización de dependencias.
4. **Ejecutar:** Compila y ejecuta en un dispositivo o emulador con acceso a Internet.
## 📂 Estructura del Proyecto ## 📂 Estructura del Proyecto
- `app/`: Contiene el código fuente principal de la aplicación. - `app/`: Módulo principal de la aplicación.
- `src/main/java/com/example/saludapp/MainActivity.kt`: Punto de entrada de la aplicación. - `src/main/java/com/example/saludapp/`:
- `src/main/java/com/example/saludapp/ui/StartScreen.kt`: Composable de la pantalla de inicio. - `MainActivity.kt`: Gestiona el flujo de navegación principal.
- `src/main/java/com/example/saludapp/ui/theme/`: Configuración del tema, colores y tipografía de Material 3. - `data/DatabaseHelper.kt`: Lógica de conexión y consultas a MariaDB.
- `ui/`: Contiene los componentes de la interfaz de usuario.
- `StartScreen.kt`: Pantalla de bienvenida.
- `LoginScreen.kt`: Interfaz de inicio de sesión con validación real.
- `theme/`: Definición de estilos y colores de Material 3.
--- ---
Desarrollado con ❤️ para mejorar la salud de los usuarios. Desarrollado con ❤️ para mejorar la salud de los usuarios.
+1
View File
@@ -42,6 +42,7 @@ dependencies {
implementation(libs.androidx.compose.ui.tooling.preview) implementation(libs.androidx.compose.ui.tooling.preview)
implementation(libs.androidx.core.ktx) implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.mariadb.java.client)
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(platform(libs.androidx.compose.bom)) androidTestImplementation(platform(libs.androidx.compose.bom))
androidTestImplementation(libs.androidx.compose.ui.test.junit4) androidTestImplementation(libs.androidx.compose.ui.test.junit4)
+2
View File
@@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<application <application
android:allowBackup="true" android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules" android:dataExtractionRules="@xml/data_extraction_rules"
@@ -4,6 +4,16 @@ import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.example.saludapp.ui.LoginScreen
import com.example.saludapp.ui.StartScreen import com.example.saludapp.ui.StartScreen
import com.example.saludapp.ui.theme.SaludappTheme import com.example.saludapp.ui.theme.SaludappTheme
@@ -13,8 +23,24 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
SaludappTheme { SaludappTheme {
StartScreen { var currentScreen by remember { mutableStateOf("start") }
// Acción al presionar el botón
when (currentScreen) {
"start" -> StartScreen {
currentScreen = "login"
}
"login" -> LoginScreen {
// Aquí iría la lógica tras login exitoso
currentScreen = "home"
}
"home" -> {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text("Bienvenido a Saludapp")
}
}
} }
} }
} }
@@ -0,0 +1,43 @@
package com.example.saludapp.data
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.sql.Connection
import java.sql.DriverManager
import java.sql.SQLException
object DatabaseHelper {
private const val URL = "jdbc:mariadb://mariadb.peta9.com:3306/saludapp_db"
private const val USER = "saludapp_dba"
private const val PASSWORD = "TU_CONTRASEÑA_AQUÍ" // TODO: Reemplazar con la contraseña real
suspend fun validateLogin(user: String, pass: String): Boolean = withContext(Dispatchers.IO) {
var connection: Connection? = null
try {
// Cargar el driver explícitamente si es necesario
Class.forName("org.mariadb.jdbc.Driver")
connection = DriverManager.getConnection(URL, USER, PASSWORD)
val query = "SELECT COUNT(*) FROM usuarios WHERE (username = ? OR email = ?) AND password = ?"
connection.prepareStatement(query).use { statement ->
statement.setString(1, user)
statement.setString(2, user)
statement.setString(3, pass)
val resultSet = statement.executeQuery()
if (resultSet.next()) {
return@withContext resultSet.getInt(1) > 0
}
}
} catch (e: Exception) {
e.printStackTrace()
} finally {
try {
connection?.close()
} catch (e: SQLException) {
e.printStackTrace()
}
}
return@withContext false
}
}
@@ -0,0 +1,102 @@
package com.example.saludapp.ui
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import com.example.saludapp.data.DatabaseHelper
import kotlinx.coroutines.launch
@Composable
fun LoginScreen(onLoginSuccess: () -> Unit) {
var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var isLoading by remember { mutableStateOf(false) }
var errorMessage by remember { mutableStateOf<String?>(null) }
val scope = rememberCoroutineScope()
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text(
text = "Iniciar Sesión",
style = MaterialTheme.typography.headlineMedium,
color = MaterialTheme.colorScheme.primary
)
Spacer(modifier = Modifier.height(32.dp))
OutlinedTextField(
value = email,
onValueChange = { email = it },
label = { Text("Usuario o Email") },
modifier = Modifier.fillMaxWidth(),
singleLine = true,
enabled = !isLoading
)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = password,
onValueChange = { password = it },
label = { Text("Contraseña") },
visualTransformation = PasswordVisualTransformation(),
modifier = Modifier.fillMaxWidth(),
singleLine = true,
enabled = !isLoading
)
if (errorMessage != null) {
Text(
text = errorMessage!!,
color = MaterialTheme.colorScheme.error,
modifier = Modifier.padding(top = 16.dp)
)
}
Spacer(modifier = Modifier.height(32.dp))
Button(
onClick = {
scope.launch {
isLoading = true
errorMessage = null
val success = DatabaseHelper.validateLogin(email, password)
isLoading = false
if (success) {
onLoginSuccess()
} else {
errorMessage = "Usuario o contraseña incorrectos"
}
}
},
modifier = Modifier
.fillMaxWidth()
.height(56.dp),
enabled = !isLoading && email.isNotEmpty() && password.isNotEmpty()
) {
if (isLoading) {
CircularProgressIndicator(
modifier = Modifier.size(24.dp),
color = MaterialTheme.colorScheme.onPrimary,
strokeWidth = 2.dp
)
} else {
Text("Entrar")
}
}
}
}
}
+2
View File
@@ -8,8 +8,10 @@ lifecycleRuntimeKtx = "2.11.0"
activityCompose = "1.13.0" activityCompose = "1.13.0"
kotlin = "2.2.10" kotlin = "2.2.10"
composeBom = "2026.02.01" composeBom = "2026.02.01"
mariadb = "3.5.1"
[libraries] [libraries]
mariadb-java-client = { group = "org.mariadb.jdbc", name = "mariadb-java-client", version.ref = "mariadb" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" } junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }