added passwort for login and download, token-system
This commit is contained in:
@ -16,21 +16,24 @@ import javax.crypto.spec.SecretKeySpec
|
||||
object DatabaseDownloader {
|
||||
|
||||
private const val DB_NAME = "questionnaire_database"
|
||||
private const val API_TOKEN = "MEIN_SUPER_GEHEIMES_TOKEN_12345"
|
||||
private const val SERVER_DOWNLOAD_URL = "http://49.13.157.44/downloadFull.php?token=$API_TOKEN"
|
||||
private const val SERVER_DOWNLOAD_URL = "http://49.13.157.44/downloadFull.php"
|
||||
|
||||
// AES-256 Key (muss exakt 32 Bytes lang sein)
|
||||
private const val AES_KEY = "12345678901234567890123456789012"
|
||||
|
||||
private val client = OkHttpClient()
|
||||
|
||||
fun downloadAndReplaceDatabase(context: Context) {
|
||||
/**
|
||||
* Startet den Download und Austausch der DB, benötigt gültiges Token
|
||||
*/
|
||||
fun downloadAndReplaceDatabase(context: Context, token: String) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
Log.d("DOWNLOAD", "Download gestartet: $SERVER_DOWNLOAD_URL")
|
||||
|
||||
val request = Request.Builder()
|
||||
.url(SERVER_DOWNLOAD_URL)
|
||||
.header("Authorization", "Bearer $token")
|
||||
.build()
|
||||
|
||||
val response = client.newCall(request).execute()
|
||||
|
||||
@ -20,14 +20,32 @@ import kotlin.system.exitProcess
|
||||
object DatabaseUploader {
|
||||
|
||||
private const val DB_NAME = "questionnaire_database"
|
||||
// TODO entferne uploadDeltaTest2.php
|
||||
private const val SERVER_DELTA_URL = "http://49.13.157.44/uploadDeltaTest3.php"
|
||||
private const val SERVER_DELTA_URL = "http://49.13.157.44/uploadDeltaTest4.php"
|
||||
private const val SERVER_CHECK_URL = "http://49.13.157.44/checkDatabaseExists.php"
|
||||
private const val API_TOKEN = "MEIN_SUPER_GEHEIMES_TOKEN_12345"
|
||||
|
||||
private val client = OkHttpClient()
|
||||
|
||||
fun uploadDatabase(context: Context) {
|
||||
/**
|
||||
* Startet den Upload mit Login über LoginManager.
|
||||
* @param context Android Context
|
||||
* @param password Vom User eingegebenes Passwort
|
||||
*/
|
||||
fun uploadDatabaseWithLogin(context: Context, password: String) {
|
||||
LoginManager.loginUser(context, password,
|
||||
onSuccess = { token ->
|
||||
Log.d("UPLOAD", "Login erfolgreich, Token erhalten")
|
||||
uploadDatabase(context, token)
|
||||
},
|
||||
onError = { errorMsg ->
|
||||
Log.e("UPLOAD", "Login fehlgeschlagen: $errorMsg")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Interner Upload, benötigt gültiges Token
|
||||
*/
|
||||
private fun uploadDatabase(context: Context, token: String) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val dbFile = context.getDatabasePath(DB_NAME)
|
||||
@ -45,9 +63,7 @@ object DatabaseUploader {
|
||||
)
|
||||
db.rawQuery("PRAGMA wal_checkpoint(FULL);", null).use { cursor ->
|
||||
if (cursor.moveToFirst()) {
|
||||
try {
|
||||
Log.d("UPLOAD", "WAL-Checkpoint result: ${cursor.getInt(0)}")
|
||||
} catch (_: Exception) {}
|
||||
try { Log.d("UPLOAD", "WAL-Checkpoint result: ${cursor.getInt(0)}") } catch (_: Exception) {}
|
||||
}
|
||||
}
|
||||
db.close()
|
||||
@ -59,12 +75,12 @@ object DatabaseUploader {
|
||||
val exists = checkDatabaseExists()
|
||||
if (exists) {
|
||||
Log.d("UPLOAD", "Server-Datenbank vorhanden → Delta-Upload")
|
||||
uploadPseudoDelta(context, dbFile)
|
||||
} else {
|
||||
Log.d("UPLOAD", "Keine Server-Datenbank → Delta-Upload")
|
||||
uploadPseudoDelta(context, dbFile)
|
||||
}
|
||||
|
||||
uploadPseudoDelta(context, dbFile, token)
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e("UPLOAD", "Fehler beim Hochladen der DB", e)
|
||||
}
|
||||
@ -97,15 +113,7 @@ object DatabaseUploader {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wichtig: Diese Funktion wurde erweitert, sodass:
|
||||
* - die DB als JSON in eine temporäre Datei geschrieben wird,
|
||||
* - diese JSON-Datei AES-verschlüsselt wird (mit AES256Helper.encryptFile),
|
||||
* - die verschlüsselte Datei als Multipart 'file' an den Server gesendet wird.
|
||||
*
|
||||
* (Funktionalität: gleiche Signatur wie vorher behalten)
|
||||
*/
|
||||
private fun uploadPseudoDelta(context: Context, file: File) {
|
||||
private fun uploadPseudoDelta(context: Context, file: File, token: String) {
|
||||
try {
|
||||
val db = SQLiteDatabase.openDatabase(file.absolutePath, null, SQLiteDatabase.OPEN_READONLY)
|
||||
|
||||
@ -125,25 +133,21 @@ object DatabaseUploader {
|
||||
|
||||
db.close()
|
||||
|
||||
// Schreibe JSON in temporäre Datei
|
||||
val tmpJson = File(context.cacheDir, "payload.json")
|
||||
tmpJson.writeText(data.toString())
|
||||
|
||||
// Verschlüssele JSON -> tmpEnc
|
||||
val tmpEnc = File(context.cacheDir, "payload.enc")
|
||||
try {
|
||||
AES256Helper.encryptFile(tmpJson, tmpEnc)
|
||||
} catch (e: Exception) {
|
||||
Log.e("UPLOAD", "Fehler bei der Verschlüsselung der JSON-Datei", e)
|
||||
// cleanup
|
||||
tmpJson.delete()
|
||||
return
|
||||
}
|
||||
|
||||
val requestBody = MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart("token", API_TOKEN)
|
||||
// Datei-Feld "file" mit verschlüsselter Payload
|
||||
.addFormDataPart("token", token) // Token vom Login
|
||||
.addFormDataPart(
|
||||
"file",
|
||||
"payload.enc",
|
||||
@ -159,31 +163,19 @@ object DatabaseUploader {
|
||||
client.newCall(request).enqueue(object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
Log.e("UPLOAD", "Delta-Upload fehlgeschlagen: ${e.message}")
|
||||
// cleanup
|
||||
tmpJson.delete()
|
||||
tmpEnc.delete()
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
val body = try {
|
||||
response.body?.string() ?: "Keine Response"
|
||||
} catch (e: Exception) {
|
||||
val body = try { response.body?.string() ?: "Keine Response" } catch (e: Exception) {
|
||||
"Fehler beim Lesen der Response: ${e.message}"
|
||||
}
|
||||
if (response.isSuccessful) {
|
||||
Log.d("UPLOAD", "Delta-Upload erfolgreich: $body")
|
||||
// Lösche Hauptdatenbank
|
||||
if (file.delete()) {
|
||||
Log.d("UPLOAD", "Lokale DB gelöscht.")
|
||||
} else {
|
||||
Log.e("UPLOAD", "Löschen der lokalen DB fehlgeschlagen.")
|
||||
}
|
||||
// Lösche Journal-Datei
|
||||
if (file.delete()) Log.d("UPLOAD", "Lokale DB gelöscht.") else Log.e("UPLOAD", "Löschen der lokalen DB fehlgeschlagen.")
|
||||
val journalFile = File(file.parent, file.name + "-journal")
|
||||
if (journalFile.exists() && journalFile.delete()) {
|
||||
Log.d("UPLOAD", "Journal-Datei gelöscht.")
|
||||
}
|
||||
// cleanup temp files
|
||||
if (journalFile.exists() && journalFile.delete()) Log.d("UPLOAD", "Journal-Datei gelöscht.")
|
||||
tmpJson.delete()
|
||||
tmpEnc.delete()
|
||||
exitProcess(0)
|
||||
|
||||
@ -69,10 +69,9 @@ class HandlerClientCoachCode(
|
||||
val clientCode = clientCodeField.text.toString()
|
||||
val coachCode = coachCodeField.text.toString()
|
||||
|
||||
// Prüfen, ob die Datenbank-Dateien vor dem Klick existieren
|
||||
val dbFile = layout.context.getDatabasePath("questionnaire_database")
|
||||
val dbJournalFile = layout.context.getDatabasePath("questionnaire_database-journal")
|
||||
val dbExisted = dbFile.exists() || dbJournalFile.exists()
|
||||
// Prüfen, ob die DB-Datei vor dem Zugriff existiert
|
||||
val dbPath = layout.context.getDatabasePath("questionnaire_database")
|
||||
val dbExistedBefore = dbPath.exists()
|
||||
|
||||
// Check if client code already exists asynchronously
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
@ -86,19 +85,21 @@ class HandlerClientCoachCode(
|
||||
} else {
|
||||
// Either no existing client or re-using previous code
|
||||
saveAnswers(clientCode, coachCode)
|
||||
|
||||
// Datenbank-Dateien löschen, wenn sie vorher NICHT existierten
|
||||
if (!dbExisted) {
|
||||
dbFile.delete()
|
||||
dbJournalFile.delete()
|
||||
}
|
||||
|
||||
goToNextQuestion()
|
||||
|
||||
// Lösche DB-Dateien nur, wenn sie vorher nicht existierten
|
||||
if (!dbExistedBefore) {
|
||||
MyApp.database.close()
|
||||
dbPath.delete()
|
||||
val journalFile = layout.context.getDatabasePath("questionnaire_database-journal")
|
||||
journalFile.delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Handle Previous button click
|
||||
private fun onPreviousClicked(clientCodeField: EditText, coachCodeField: EditText) {
|
||||
val clientCode = clientCodeField.text.toString()
|
||||
|
||||
@ -13,7 +13,7 @@ import android.util.Log
|
||||
import com.dano.test1.data.CompletedQuestionnaire
|
||||
import java.io.File
|
||||
|
||||
var INTEGRATION_INDEX_POINTS: Int? = null
|
||||
var RHS_POINTS: Int? = null
|
||||
|
||||
class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
|
||||
@ -342,13 +342,12 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
MyApp.database.completedQuestionnaireDao().getAllForClient(clientCode)
|
||||
}
|
||||
|
||||
// fülle buttonPoints & INTEGRATION_INDEX_POINTS
|
||||
buttonPoints.clear()
|
||||
for (entry in completedEntries) {
|
||||
if (entry.isDone) {
|
||||
buttonPoints[entry.questionnaireId] = entry.sumPoints ?: 0
|
||||
if (entry.questionnaireId.contains("questionnaire_3_integration_index", ignoreCase = true)) {
|
||||
INTEGRATION_INDEX_POINTS = entry.sumPoints
|
||||
if (entry.questionnaireId.contains("questionnaire_2_rhs", ignoreCase = true)) {
|
||||
RHS_POINTS = entry.sumPoints
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -682,39 +681,79 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
uploadButton.setOnClickListener {
|
||||
val clientCode = editText.text.toString().trim()
|
||||
|
||||
if (clientCode.isBlank()) {
|
||||
val message = LanguageManager.getText(languageID, "please_client_code")
|
||||
Toast.makeText(activity, message, Toast.LENGTH_SHORT).show()
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
||||
GlobalValues.LAST_CLIENT_CODE = clientCode
|
||||
|
||||
Toast.makeText(activity, "Datenbank wird hochgeladen...", Toast.LENGTH_SHORT).show()
|
||||
DatabaseUploader.uploadDatabase(activity)
|
||||
// Passwort-Eingabe-Popup
|
||||
val input = EditText(activity).apply {
|
||||
hint = "Server-Passwort"
|
||||
}
|
||||
|
||||
android.app.AlertDialog.Builder(activity)
|
||||
.setTitle("Login erforderlich")
|
||||
.setView(input)
|
||||
.setPositiveButton("OK") { _, _ ->
|
||||
val password = input.text.toString()
|
||||
if (password.isNotBlank()) {
|
||||
Toast.makeText(activity, "Login wird überprüft...", Toast.LENGTH_SHORT).show()
|
||||
// Login + Upload starten
|
||||
DatabaseUploader.uploadDatabaseWithLogin(activity, password)
|
||||
} else {
|
||||
Toast.makeText(activity, "Bitte Passwort eingeben", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
.setNegativeButton("Abbrechen", null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
// --- Füge diese Funktion in deine Klasse ein ---
|
||||
private fun isDatabasePopulated(): Boolean {
|
||||
return try {
|
||||
val db = MyApp.database.openHelper.readableDatabase
|
||||
val cursor = db.query(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name != 'room_master_table'"
|
||||
)
|
||||
cursor.use { it.count > 0 }
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun setupDownloadButton() {
|
||||
downloadButton.text = "Download"
|
||||
downloadButton.setOnClickListener {
|
||||
val clientCode = editText.text.toString().trim()
|
||||
|
||||
GlobalValues.LAST_CLIENT_CODE = clientCode
|
||||
|
||||
Toast.makeText(activity, "Datenbank wird heruntergeladen...", Toast.LENGTH_SHORT).show()
|
||||
DatabaseDownloader.downloadAndReplaceDatabase(activity)
|
||||
updateMainButtonsState(true)
|
||||
// Eingabe-Popup für Passwort anzeigen
|
||||
val input = EditText(activity).apply {
|
||||
hint = "Server-Passwort"
|
||||
}
|
||||
|
||||
android.app.AlertDialog.Builder(activity)
|
||||
.setTitle("Login erforderlich")
|
||||
.setView(input)
|
||||
.setPositiveButton("OK") { _, _ ->
|
||||
val password = input.text.toString()
|
||||
if (password.isNotBlank()) {
|
||||
// Login starten
|
||||
LoginManager.loginUser(
|
||||
context = activity,
|
||||
password = password,
|
||||
onSuccess = { token ->
|
||||
Toast.makeText(activity, "Login erfolgreich", Toast.LENGTH_SHORT).show()
|
||||
DatabaseDownloader.downloadAndReplaceDatabase(activity, token)
|
||||
updateMainButtonsState(true)
|
||||
},
|
||||
onError = { error ->
|
||||
Toast.makeText(activity, error, Toast.LENGTH_LONG).show()
|
||||
}
|
||||
)
|
||||
} else {
|
||||
Toast.makeText(activity, "Bitte Passwort eingeben", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
.setNegativeButton("Abbrechen", null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun updateMainButtonsState(isDatabaseAvailable: Boolean) {
|
||||
val buttons = listOf(buttonLoad, saveButton, editButton)
|
||||
buttons.forEach { button ->
|
||||
|
||||
@ -17,7 +17,7 @@ object LanguageManager {
|
||||
}
|
||||
|
||||
private fun injectDynamicValues(text: String): String {
|
||||
val points = INTEGRATION_INDEX_POINTS ?: 0
|
||||
val points = RHS_POINTS ?: 0
|
||||
val color = when (points) {
|
||||
in 1..12 -> "#4CAF50" // Grün
|
||||
in 13..36 -> "#FFEB3B" // Gelb
|
||||
@ -26,7 +26,7 @@ object LanguageManager {
|
||||
}
|
||||
|
||||
val coloredPoints = "<b><font color='$color'>$points</font></b>"
|
||||
return text.replace("INTEGRATION_INDEX_POINTS", coloredPoints)
|
||||
return text.replace("RHS_POINTS", coloredPoints)
|
||||
}
|
||||
|
||||
// Sprachdatenbank: Map<Sprachcode, Map<Text-ID, Text>>
|
||||
@ -285,7 +285,7 @@ object LanguageManager {
|
||||
"select_one_answer_per_row" to "Bitte wählen Sie eine Antwort pro Reihe aus!",
|
||||
"no_next_question_defined" to "Keine Weiterleitungsseite definiert",
|
||||
"date_consultation_health_interview_result" to "Datum Beratungsgespräch (zum Ergebnis Gesundheitsinterview grün/gelb/rot)",
|
||||
"consultation_decision" to "Beratungsentscheidung (INTEGRATION_INDEX_POINTS)",
|
||||
"consultation_decision" to "Beratungsentscheidung (RHS_POINTS)",
|
||||
"consent_conversation_in_6_months" to "Einverständnis Gespräch in 6 Monaten:",
|
||||
"participation_in_coaching" to "Teilnahme am Coaching",
|
||||
"decision_after_reflection_period" to "Entscheidung am .............. (Datum) nach Bedenkzeit",
|
||||
@ -580,7 +580,7 @@ object LanguageManager {
|
||||
"select_one_answer_per_row" to "Please select one answer per row!",
|
||||
"no_next_question_defined" to "No forwarding page defined",
|
||||
"date_consultation_health_interview_result" to "Date of counseling interview (health interview result green/yellow/red)",
|
||||
"consultation_decision" to "Counseling decision (INTEGRATION_INDEX_POINTS)",
|
||||
"consultation_decision" to "Counseling decision (RHS_POINTS)",
|
||||
"consent_conversation_in_6_months" to "Consent for conversation in 6 months:",
|
||||
"participation_in_coaching" to "Participation in coaching",
|
||||
"decision_after_reflection_period" to "Decision on .............. (date) after reflection period",
|
||||
@ -878,7 +878,7 @@ object LanguageManager {
|
||||
"select_one_answer_per_row" to "Veuillez sélectionner une réponse par ligne !",
|
||||
"no_next_question_defined" to "Aucune page de redirection définie",
|
||||
"date_consultation_health_interview_result" to "Date de l’entretien de conseil (résultat de l’entretien santé vert/jaune/rouge)",
|
||||
"consultation_decision" to "Décision de conseil (INTEGRATION_INDEX_POINTS)",
|
||||
"consultation_decision" to "Décision de conseil (RHS_POINTS)",
|
||||
"consent_conversation_in_6_months" to "Consentement pour entretien dans 6 mois :",
|
||||
"participation_in_coaching" to "Participation au coaching",
|
||||
"decision_after_reflection_period" to "Décision le .............. (date) après période de réflexion",
|
||||
@ -1172,7 +1172,7 @@ object LanguageManager {
|
||||
"select_one_answer_per_row" to "Пожалуйста, выберите один ответ в каждой строке!",
|
||||
"no_next_question_defined" to "Следующая страница не определена",
|
||||
"date_consultation_health_interview_result" to "Дата консультации (результат медицинского интервью: зеленый/желтый/красный)",
|
||||
"consultation_decision" to "Решение по консультации (INTEGRATION_INDEX_POINTS)",
|
||||
"consultation_decision" to "Решение по консультации (RHS_POINTS)",
|
||||
"consent_conversation_in_6_months" to "Согласие на разговор через 6 месяцев:",
|
||||
"participation_in_coaching" to "Участие в коучинге",
|
||||
"decision_after_reflection_period" to "Решение от .............. (дата) после периода раздумий",
|
||||
@ -1470,7 +1470,7 @@ object LanguageManager {
|
||||
"select_one_answer_per_row" to "Будь ласка, оберіть по одній відповіді в кожному рядку!",
|
||||
"no_next_question_defined" to "Наступна сторінка не визначена",
|
||||
"date_consultation_health_interview_result" to "Дата консультації (результат медичного інтерв’ю зелений/жовтий/червоний)",
|
||||
"consultation_decision" to "Рішення консультації (INTEGRATION_INDEX_POINTS)",
|
||||
"consultation_decision" to "Рішення консультації (RHS_POINTS)",
|
||||
"consent_conversation_in_6_months" to "Згода на розмову через 6 місяців:",
|
||||
"participation_in_coaching" to "Участь у коучингу",
|
||||
"decision_after_reflection_period" to "Рішення .............. (дата) після періоду роздумів",
|
||||
@ -1768,7 +1768,7 @@ object LanguageManager {
|
||||
"select_one_answer_per_row" to "Lütfen her satır için bir cevap seçin!",
|
||||
"no_next_question_defined" to "Bir yönlendirme sayfası tanımlanmadı",
|
||||
"date_consultation_health_interview_result" to "Danışma görüşmesi tarihi (sağlık görüşmesi sonucu yeşil/sarı/kırmızı)",
|
||||
"consultation_decision" to "Danışma kararı (INTEGRATION_INDEX_POINTS)",
|
||||
"consultation_decision" to "Danışma kararı (RHS_POINTS)",
|
||||
"consent_conversation_in_6_months" to "6 ay içinde görüşme onayı:",
|
||||
"participation_in_coaching" to "Koçluğa katılım",
|
||||
"decision_after_reflection_period" to "Karar .............. (tarih) tarihinde düşünme süresinden sonra verildi",
|
||||
@ -2066,7 +2066,7 @@ object LanguageManager {
|
||||
"select_one_answer_per_row" to "Proszę wybrać jedną odpowiedź w każdym wierszu!",
|
||||
"no_next_question_defined" to "Nie zdefiniowano strony przekierowania",
|
||||
"date_consultation_health_interview_result" to "Data rozmowy doradczej (wynik wywiadu zdrowotnego: zielony/żółty/czerwony)",
|
||||
"consultation_decision" to "Decyzja doradcza (INTEGRATION_INDEX_POINTS)",
|
||||
"consultation_decision" to "Decyzja doradcza (RHS_POINTS)",
|
||||
"consent_conversation_in_6_months" to "Zgoda na rozmowę za 6 miesięcy:",
|
||||
"participation_in_coaching" to "Udział w coachingu",
|
||||
"decision_after_reflection_period" to "Decyzja dnia .............. (data) po czasie do namysłu",
|
||||
@ -2662,7 +2662,7 @@ object LanguageManager {
|
||||
"select_one_answer_per_row" to "Vă rugăm să selectați un răspuns pe rând!",
|
||||
"no_next_question_defined" to "Nu este definită o pagină de redirecționare",
|
||||
"date_consultation_health_interview_result" to "Data consilierii (rezultatul interviului de sănătate verde/galben/roșu)",
|
||||
"consultation_decision" to "Decizia consilierii (INTEGRATION_INDEX_POINTS)",
|
||||
"consultation_decision" to "Decizia consilierii (RHS_POINTS)",
|
||||
"consent_conversation_in_6_months" to "Consimțământ discuție peste 6 luni:",
|
||||
"participation_in_coaching" to "Participare la coaching",
|
||||
"decision_after_reflection_period" to "Decizie la .............. (dată) după perioada de reflecție",
|
||||
@ -2960,7 +2960,7 @@ object LanguageManager {
|
||||
"select_one_answer_per_row" to "Por favor, seleccione una respuesta por fila.",
|
||||
"no_next_question_defined" to "No se definió ninguna pregunta de continuación",
|
||||
"date_consultation_health_interview_result" to "Fecha de la entrevista de orientación (sobre el resultado de la entrevista de salud: verde/amarillo/rojo)",
|
||||
"consultation_decision" to "Decisión de orientación (INTEGRATION_INDEX_POINTS)",
|
||||
"consultation_decision" to "Decisión de orientación (RHS_POINTS)",
|
||||
"consent_conversation_in_6_months" to "Consentimiento para entrevista en 6 meses:",
|
||||
"participation_in_coaching" to "Participación en el coaching",
|
||||
"decision_after_reflection_period" to "Decisión tomada el .............. (fecha) después del período de reflexión",
|
||||
|
||||
72
app/src/main/java/com/dano/test1/LoginManager.kt
Normal file
72
app/src/main/java/com/dano/test1/LoginManager.kt
Normal file
@ -0,0 +1,72 @@
|
||||
package com.dano.test1
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import org.json.JSONObject
|
||||
|
||||
object LoginManager {
|
||||
|
||||
private const val SERVER_LOGIN_URL = "http://49.13.157.44/login.php"
|
||||
private val client = OkHttpClient()
|
||||
|
||||
/**
|
||||
* Startet den Login-Prozess.
|
||||
*
|
||||
* @param context Android Context
|
||||
* @param password Vom User eingegebenes Passwort
|
||||
* @param onSuccess Callback mit dem Token wenn Login erfolgreich
|
||||
* @param onError Callback mit Fehlermeldung
|
||||
*/
|
||||
fun loginUser(
|
||||
context: Context,
|
||||
password: String,
|
||||
onSuccess: (String) -> Unit,
|
||||
onError: (String) -> Unit
|
||||
) {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
try {
|
||||
val requestBody = """{"password":"$password"}"""
|
||||
.toRequestBody("application/json".toMediaType())
|
||||
|
||||
val request = Request.Builder()
|
||||
.url(SERVER_LOGIN_URL)
|
||||
.post(requestBody)
|
||||
.build()
|
||||
|
||||
val response = client.newCall(request).execute()
|
||||
val responseText = response.body?.string()
|
||||
|
||||
if (response.isSuccessful && responseText != null) {
|
||||
val json = JSONObject(responseText)
|
||||
if (json.getBoolean("success")) {
|
||||
val token = json.getString("token")
|
||||
withContext(Dispatchers.Main) {
|
||||
onSuccess(token)
|
||||
}
|
||||
} else {
|
||||
withContext(Dispatchers.Main) {
|
||||
onError("Login fehlgeschlagen")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
withContext(Dispatchers.Main) {
|
||||
onError("Fehler beim Login (${response.code})")
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("LOGIN", "Exception beim Login", e)
|
||||
withContext(Dispatchers.Main) {
|
||||
onError("Exception: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user