added deltaUpload but not working 100% in combination with fullUpload. Changed download, it is now deleting the existing database before downloading.

This commit is contained in:
oxidiert
2025-08-13 12:06:07 +02:00
parent bd8074cb13
commit 17b455a60a
2 changed files with 142 additions and 24 deletions

View File

@ -21,6 +21,16 @@ object DatabaseDownloader {
fun downloadAndReplaceDatabase(context: Context) { fun downloadAndReplaceDatabase(context: Context) {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
try { try {
// Alte DB sofort löschen, bevor irgendwas heruntergeladen wird
val dbFile = context.getDatabasePath(DB_NAME)
if (dbFile.exists()) {
if (dbFile.delete()) {
Log.d("DOWNLOAD", "Bestehende lokale DB gelöscht.")
} else {
Log.e("DOWNLOAD", "Konnte bestehende DB nicht löschen.")
}
}
Log.d("DOWNLOAD", "Download gestartet: $SERVER_DOWNLOAD_URL") Log.d("DOWNLOAD", "Download gestartet: $SERVER_DOWNLOAD_URL")
val request = Request.Builder() val request = Request.Builder()
@ -41,10 +51,7 @@ object DatabaseDownloader {
} }
Log.d("DOWNLOAD", "Datei gespeichert: ${downloadedFile.absolutePath}") Log.d("DOWNLOAD", "Datei gespeichert: ${downloadedFile.absolutePath}")
val dbFile = context.getDatabasePath(DB_NAME)
if (dbFile.exists()) dbFile.delete()
downloadedFile.copyTo(dbFile, overwrite = true) downloadedFile.copyTo(dbFile, overwrite = true)
Log.d("DOWNLOAD", "Neue DB erfolgreich eingesetzt") Log.d("DOWNLOAD", "Neue DB erfolgreich eingesetzt")
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -2,13 +2,17 @@ package com.dano.test1
import android.content.Context import android.content.Context
import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteDatabase
import android.util.Base64
import android.util.Log import android.util.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import android.database.Cursor
import okhttp3.* import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.asRequestBody
import org.json.JSONArray
import org.json.JSONObject
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import kotlin.system.exitProcess import kotlin.system.exitProcess
@ -16,7 +20,9 @@ import kotlin.system.exitProcess
object DatabaseUploader { object DatabaseUploader {
private const val DB_NAME = "questionnaire_database" private const val DB_NAME = "questionnaire_database"
private const val SERVER_UPLOAD_URL = "http://49.13.157.44/uploadFull.php" private const val SERVER_FULL_URL = "http://49.13.157.44/uploadFull.php"
private const val SERVER_DELTA_URL = "http://49.13.157.44/uploadDelta.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 const val API_TOKEN = "MEIN_SUPER_GEHEIMES_TOKEN_12345"
private val client = OkHttpClient() private val client = OkHttpClient()
@ -30,21 +36,34 @@ object DatabaseUploader {
return@launch return@launch
} }
// WAL-Daten in die Hauptdatei schreiben // WAL-Checkpoint
try { try {
val db = SQLiteDatabase.openDatabase( val db = SQLiteDatabase.openDatabase(
dbFile.absolutePath, dbFile.absolutePath,
null, null,
SQLiteDatabase.OPEN_READWRITE SQLiteDatabase.OPEN_READWRITE
) )
db.execSQL("PRAGMA wal_checkpoint(FULL);") db.rawQuery("PRAGMA wal_checkpoint(FULL);", null).use { cursor ->
if (cursor.moveToFirst()) {
try {
Log.d("UPLOAD", "WAL-Checkpoint result: ${cursor.getInt(0)}")
} catch (_: Exception) {}
}
}
db.close() db.close()
Log.d("UPLOAD", "WAL-Checkpoint erfolgreich durchgeführt.") Log.d("UPLOAD", "WAL-Checkpoint erfolgreich.")
} catch (e: Exception) { } catch (e: Exception) {
Log.e("UPLOAD", "Fehler beim WAL-Checkpoint", e) Log.e("UPLOAD", "Fehler beim WAL-Checkpoint", e)
} }
uploadFile(dbFile) val exists = checkDatabaseExists()
if (exists) {
Log.d("UPLOAD", "Server-Datenbank vorhanden → Delta-Upload")
uploadDelta(dbFile)
} else {
Log.d("UPLOAD", "Keine Server-Datenbank → Full-Upload")
uploadFull(dbFile)
}
} catch (e: Exception) { } catch (e: Exception) {
Log.e("UPLOAD", "Fehler beim Hochladen der DB", e) Log.e("UPLOAD", "Fehler beim Hochladen der DB", e)
@ -52,7 +71,33 @@ object DatabaseUploader {
} }
} }
private fun uploadFile(file: File) { private fun checkDatabaseExists(): Boolean {
return try {
val request = Request.Builder()
.url(SERVER_CHECK_URL)
.get()
.build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
Log.e("UPLOAD", "checkDatabaseExists HTTP error: ${response.code}")
return false
}
val body = response.body?.string() ?: return false
try {
val j = JSONObject(body)
j.optBoolean("exists", false)
} catch (e: Exception) {
body.contains("exists", ignoreCase = true)
}
}
} catch (e: Exception) {
Log.e("UPLOAD", "Fehler bei Server-Prüfung", e)
false
}
}
private fun uploadFull(file: File) {
val requestBody = MultipartBody.Builder() val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM) .setType(MultipartBody.FORM)
.addFormDataPart( .addFormDataPart(
@ -63,18 +108,85 @@ object DatabaseUploader {
.build() .build()
val request = Request.Builder() val request = Request.Builder()
.url(SERVER_UPLOAD_URL) .url(SERVER_FULL_URL)
.post(requestBody) .post(requestBody)
.build() .build()
client.newCall(request).enqueue(object : Callback { client.newCall(request).enqueue(serverCallback(file))
}
private fun uploadDelta(file: File) {
try {
val db = SQLiteDatabase.openDatabase(file.absolutePath, null, SQLiteDatabase.OPEN_READONLY)
val data = JSONObject().apply {
put("clients", queryToJsonArray(db, "SELECT clientCode FROM clients"))
put("questionnaires", queryToJsonArray(db, "SELECT id FROM questionnaires"))
put("questions", queryToJsonArray(db, "SELECT questionId, questionnaireId, question FROM questions"))
put("answers", queryToJsonArray(db, "SELECT clientCode, questionId, answerValue FROM answers"))
put("completed_questionnaires",
queryToJsonArray(db, "SELECT clientCode, questionnaireId, timestamp, isDone, sumPoints FROM completed_questionnaires")
)
}
db.close()
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("token", API_TOKEN)
.addFormDataPart("data", data.toString())
.build()
val request = Request.Builder()
.url(SERVER_DELTA_URL)
.post(requestBody)
.build()
client.newCall(request).enqueue(serverCallback(file))
} catch (e: Exception) {
Log.e("UPLOAD", "Fehler beim Delta-Upload", e)
}
}
private fun queryToJsonArray(db: SQLiteDatabase, query: String): JSONArray {
val cursor = db.rawQuery(query, null)
val jsonArray = JSONArray()
cursor.use {
val columnNames = it.columnNames
while (it.moveToNext()) {
val obj = JSONObject()
for (col in columnNames) {
val idx = it.getColumnIndex(col)
if (idx >= 0) {
when (it.getType(idx)) {
Cursor.FIELD_TYPE_INTEGER -> obj.put(col, it.getLong(idx))
Cursor.FIELD_TYPE_FLOAT -> obj.put(col, it.getDouble(idx))
Cursor.FIELD_TYPE_STRING -> obj.put(col, it.getString(idx))
Cursor.FIELD_TYPE_NULL -> obj.put(col, JSONObject.NULL)
Cursor.FIELD_TYPE_BLOB -> {
val blob = it.getBlob(idx)
obj.put(col, Base64.encodeToString(blob, Base64.NO_WRAP))
}
else -> obj.put(col, it.getString(idx))
}
}
}
jsonArray.put(obj)
}
}
return jsonArray
}
private fun serverCallback(file: File) = object : Callback {
override fun onFailure(call: Call, e: IOException) { override fun onFailure(call: Call, e: IOException) {
Log.e("UPLOAD", "Upload fehlgeschlagen: ${e.message}") Log.e("UPLOAD", "Upload fehlgeschlagen: ${e.message}")
} }
override fun onResponse(call: Call, response: Response) { override fun onResponse(call: Call, response: Response) {
val body = try { response.body?.string() ?: "Keine Response" } catch (e: Exception) { "Fehler beim Lesen der Response: ${e.message}" }
if (response.isSuccessful) { if (response.isSuccessful) {
Log.d("UPLOAD", "Upload erfolgreich: ${response.message}") Log.d("UPLOAD", "Upload erfolgreich: $body")
if (file.delete()) { if (file.delete()) {
Log.d("UPLOAD", "Lokale DB gelöscht.") Log.d("UPLOAD", "Lokale DB gelöscht.")
exitProcess(0) exitProcess(0)
@ -82,9 +194,8 @@ object DatabaseUploader {
Log.e("UPLOAD", "Löschen der lokalen DB fehlgeschlagen.") Log.e("UPLOAD", "Löschen der lokalen DB fehlgeschlagen.")
} }
} else { } else {
Log.e("UPLOAD", "Upload fehlgeschlagen: ${response.code} ${response.message}") Log.e("UPLOAD", "Upload fehlgeschlagen: ${response.code} $body")
} }
} }
})
} }
} }