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:
@ -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) {
|
||||||
|
|||||||
@ -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,28 +108,94 @@ 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))
|
||||||
override fun onFailure(call: Call, e: IOException) {
|
}
|
||||||
Log.e("UPLOAD", "Upload fehlgeschlagen: ${e.message}")
|
|
||||||
|
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")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResponse(call: Call, response: Response) {
|
db.close()
|
||||||
if (response.isSuccessful) {
|
|
||||||
Log.d("UPLOAD", "Upload erfolgreich: ${response.message}")
|
val requestBody = MultipartBody.Builder()
|
||||||
if (file.delete()) {
|
.setType(MultipartBody.FORM)
|
||||||
Log.d("UPLOAD", "Lokale DB gelöscht.")
|
.addFormDataPart("token", API_TOKEN)
|
||||||
exitProcess(0)
|
.addFormDataPart("data", data.toString())
|
||||||
} else {
|
.build()
|
||||||
Log.e("UPLOAD", "Löschen der lokalen DB fehlgeschlagen.")
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Log.e("UPLOAD", "Upload fehlgeschlagen: ${response.code} ${response.message}")
|
|
||||||
}
|
}
|
||||||
|
jsonArray.put(obj)
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
return jsonArray
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun serverCallback(file: File) = object : Callback {
|
||||||
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
|
Log.e("UPLOAD", "Upload fehlgeschlagen: ${e.message}")
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
Log.d("UPLOAD", "Upload erfolgreich: $body")
|
||||||
|
if (file.delete()) {
|
||||||
|
Log.d("UPLOAD", "Lokale DB gelöscht.")
|
||||||
|
exitProcess(0)
|
||||||
|
} else {
|
||||||
|
Log.e("UPLOAD", "Löschen der lokalen DB fehlgeschlagen.")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.e("UPLOAD", "Upload fehlgeschlagen: ${response.code} $body")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user