Big commit.
Managed to do upload and download right. No Race conditions.
This commit is contained in:
@ -11,7 +11,8 @@ import androidx.room.RoomDatabase
|
||||
Answer::class,
|
||||
CompletedQuestionnaire::class
|
||||
],
|
||||
version = 10
|
||||
version = 1,
|
||||
exportSchema = false
|
||||
)
|
||||
abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun clientDao(): ClientDao
|
||||
@ -20,3 +21,4 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun answerDao(): AnswerDao
|
||||
abstract fun completedQuestionnaireDao(): CompletedQuestionnaireDao
|
||||
}
|
||||
|
||||
|
||||
@ -12,8 +12,15 @@ interface ClientDao {
|
||||
|
||||
@Delete
|
||||
suspend fun deleteClient(client: Client)
|
||||
|
||||
@Query("SELECT COUNT(*) FROM clients")
|
||||
suspend fun getClientCount(): Int
|
||||
|
||||
@Query("SELECT * FROM clients")
|
||||
suspend fun getAllClients(): List<Client>
|
||||
}
|
||||
|
||||
|
||||
@Dao
|
||||
interface QuestionnaireDao {
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
|
||||
@ -18,7 +18,8 @@ import kotlin.system.exitProcess
|
||||
object DatabaseUploader {
|
||||
|
||||
private const val DB_NAME = "questionnaire_database"
|
||||
private const val SERVER_DELTA_URL = "http://49.13.157.44/uploadDelta.php"
|
||||
// TODO entferne uploadDeltaTest.php
|
||||
private const val SERVER_DELTA_URL = "http://49.13.157.44/uploadDeltaTest.php"
|
||||
private const val SERVER_CHECK_URL = "http://49.13.157.44/checkDatabaseExists.php"
|
||||
private const val API_TOKEN = "MEIN_SUPER_GEHEIMES_TOKEN_12345"
|
||||
|
||||
@ -56,10 +57,10 @@ object DatabaseUploader {
|
||||
val exists = checkDatabaseExists()
|
||||
if (exists) {
|
||||
Log.d("UPLOAD", "Server-Datenbank vorhanden → Delta-Upload")
|
||||
uploadDelta(dbFile)
|
||||
uploadPseudoDelta(dbFile)
|
||||
} else {
|
||||
Log.d("UPLOAD", "Keine Server-Datenbank → Delta-Upload")
|
||||
uploadDelta(dbFile)
|
||||
uploadPseudoDelta(dbFile)
|
||||
}
|
||||
|
||||
} catch (e: Exception) {
|
||||
@ -94,7 +95,7 @@ object DatabaseUploader {
|
||||
}
|
||||
}
|
||||
|
||||
private fun uploadDelta(file: File) {
|
||||
private fun uploadPseudoDelta(file: File) {
|
||||
try {
|
||||
val db = SQLiteDatabase.openDatabase(file.absolutePath, null, SQLiteDatabase.OPEN_READONLY)
|
||||
|
||||
@ -138,12 +139,18 @@ object DatabaseUploader {
|
||||
}
|
||||
if (response.isSuccessful) {
|
||||
Log.d("UPLOAD", "Delta-Upload erfolgreich: $body")
|
||||
// Lösche Hauptdatenbank
|
||||
if (file.delete()) {
|
||||
Log.d("UPLOAD", "Lokale DB gelöscht.")
|
||||
exitProcess(0)
|
||||
} else {
|
||||
Log.e("UPLOAD", "Löschen der lokalen DB fehlgeschlagen.")
|
||||
}
|
||||
// Lösche Journal-Datei
|
||||
val journalFile = File(file.parent, file.name + "-journal")
|
||||
if (journalFile.exists() && journalFile.delete()) {
|
||||
Log.d("UPLOAD", "Journal-Datei gelöscht.")
|
||||
}
|
||||
exitProcess(0)
|
||||
} else {
|
||||
Log.e("UPLOAD", "Delta-Upload fehlgeschlagen: ${response.code} $body")
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import android.widget.*
|
||||
import kotlinx.coroutines.*
|
||||
import org.json.JSONArray
|
||||
import android.util.Log
|
||||
import java.io.File
|
||||
|
||||
|
||||
var INTEGRATION_INDEX_POINTS: Int? = null
|
||||
@ -35,6 +36,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
activity.setContentView(R.layout.opening_screen)
|
||||
|
||||
bindViews()
|
||||
|
||||
loadQuestionnaireOrder()
|
||||
createQuestionnaireButtons()
|
||||
restorePreviousClientCode()
|
||||
@ -46,11 +48,22 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
setupUploadButton()
|
||||
setupDownloadButton()
|
||||
|
||||
val dbPath = "/data/data/com.dano.test1/databases/questionnaire_database"
|
||||
val pathExists = File(dbPath).exists()
|
||||
if (pathExists) {
|
||||
updateMainButtonsState(true)
|
||||
}
|
||||
else{
|
||||
updateMainButtonsState(false)
|
||||
}
|
||||
|
||||
if (!editText.text.isNullOrBlank()) {
|
||||
buttonLoad.performClick()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun bindViews() {
|
||||
editText = activity.findViewById(R.id.editText)
|
||||
spinner = activity.findViewById(R.id.string_spinner1)
|
||||
@ -183,13 +196,12 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
updateMainButtonsState(true) // Datenbank vorhanden -> Buttons aktivieren
|
||||
handleNormalLoad(clientCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private suspend fun handleNormalLoad(clientCode: String) {
|
||||
val completedIds = withContext(Dispatchers.IO) {
|
||||
MyApp.database.completedQuestionnaireDao().getCompletedQuestionnairesForClient(clientCode)
|
||||
@ -559,6 +571,22 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
}
|
||||
}
|
||||
|
||||
// --- Füge diese Funktion in deine Klasse ein ---
|
||||
private fun isDatabasePopulated(): Boolean {
|
||||
return try {
|
||||
// Wir prüfen, ob die Datenbank mindestens eine nicht-interne Tabelle enthält.
|
||||
// Das ist robust gegenüber verschiedenen Tabellennamen.
|
||||
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) {
|
||||
// Falls etwas schiefgeht (z.B. DB noch nicht vorhanden), gilt: nicht vorhanden
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDownloadButton() {
|
||||
downloadButton.text = "Download"
|
||||
downloadButton.setOnClickListener {
|
||||
@ -568,7 +596,15 @@ class HandlerOpeningScreen(private val activity: MainActivity) {
|
||||
|
||||
Toast.makeText(activity, "Datenbank wird heruntergeladen...", Toast.LENGTH_SHORT).show()
|
||||
DatabaseDownloader.downloadAndReplaceDatabase(activity)
|
||||
updateMainButtonsState(true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateMainButtonsState(isDatabaseAvailable: Boolean) {
|
||||
val buttons = listOf(buttonLoad, saveButton, editButton)
|
||||
buttons.forEach { button ->
|
||||
button.isEnabled = isDatabaseAvailable
|
||||
button.alpha = if (isDatabaseAvailable) 1.0f else 0.5f
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,9 @@
|
||||
package com.dano.test1
|
||||
|
||||
import android.app.Application
|
||||
import android.util.Log
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import com.dano.test1.data.AppDatabase
|
||||
|
||||
class MyApp : Application() {
|
||||
@ -13,12 +15,21 @@ class MyApp : Application() {
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
// Room Datenbank bauen: nur die Hauptdatei, ohne WAL und Journal
|
||||
database = Room.databaseBuilder(
|
||||
applicationContext,
|
||||
AppDatabase::class.java,
|
||||
"questionnaire_database"
|
||||
)
|
||||
.fallbackToDestructiveMigration()
|
||||
.setJournalMode(RoomDatabase.JournalMode.TRUNCATE) // TRUNCATE = keine -wal Datei, nur Hauptdatei
|
||||
.addCallback(object : RoomDatabase.Callback() {
|
||||
override fun onOpen(db: androidx.sqlite.db.SupportSQLiteDatabase) {
|
||||
super.onOpen(db)
|
||||
Log.d("DB", "Datenbank geöffnet. Nur questionnaire_database wird genutzt.")
|
||||
}
|
||||
})
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user