Files
Questionnaire-App/app/src/main/java/com/dano/test1/MainActivity.kt
2025-09-29 13:02:00 +02:00

224 lines
8.3 KiB
Kotlin
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.dano.test1
import android.content.res.Configuration
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
import android.os.Bundle
import android.view.View
import android.widget.EditText
import android.widget.LinearLayout
import android.widget.ProgressBar
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import java.io.File
class MainActivity : AppCompatActivity() {
private lateinit var openingScreenHandler: HandlerOpeningScreen
var isInQuestionnaire: Boolean = false
var isFirstQuestionnairePage: Boolean = false
private var progress: ProgressBar? = null
// LIVE: Network-Callback (optional für Statusleiste)
private var netCb: ConnectivityManager.NetworkCallback? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// === Offline-Start ermöglichen ===
// Bedingung: gespeicherter User/Token UND lokale DB vorhanden -> direkt OpeningScreen
val hasCreds = !TokenStore.getUsername(this).isNullOrBlank() && !TokenStore.getToken(this).isNullOrBlank()
val hasDb = hasLocalDb()
if (hasCreds && hasDb) {
openingScreenHandler = HandlerOpeningScreen(this)
openingScreenHandler.init()
return
}
// Sonst: Login-Dialog -> Login -> DB (einmalig) laden -> OpeningScreen
showLoginThenDownload()
}
/** Prüft, ob die lokale DB-Datei vorhanden ist. */
private fun hasLocalDb(): Boolean {
val dbFile = getDatabasePath("questionnaire_database")
return dbFile != null && dbFile.exists() && dbFile.length() > 0
}
/** Zeigt den Login-Dialog an, führt Login aus und lädt danach einmalig die DB. */
private fun showLoginThenDownload() {
val container = LinearLayout(this).apply {
orientation = LinearLayout.VERTICAL
setPadding(dp(20), dp(8), dp(20), 0)
}
val etUser = EditText(this).apply {
hint = "Username"
setSingleLine()
}
val etPass = EditText(this).apply {
hint = "Passwort"
setSingleLine()
inputType = android.text.InputType.TYPE_CLASS_TEXT or
android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD
}
container.addView(etUser)
container.addView(etPass)
val dialog = AlertDialog.Builder(this)
.setTitle("Login erforderlich")
.setView(container)
.setCancelable(false)
.setPositiveButton("Login") { _, _ ->
val user = etUser.text.toString().trim()
val pass = etPass.text.toString()
if (user.isEmpty() || pass.isEmpty()) {
Toast.makeText(this, "Bitte Username & Passwort eingeben", Toast.LENGTH_SHORT).show()
showLoginThenDownload()
return@setPositiveButton
}
showBusy(true)
LoginManager.loginUserWithCredentials(
context = this,
username = user,
password = pass,
onSuccess = { token ->
// Nach erfolgreichem Login: einmalig komplette DB ziehen
DatabaseDownloader.downloadAndReplaceDatabase(
context = this,
token = token
) { ok ->
showBusy(false)
// Wenn Download fehlgeschlagen ist, aber evtl. schon eine DB lokal liegt,
// lassen wir den Nutzer trotzdem weiterarbeiten (Offline).
if (!ok && !hasLocalDb()) {
Toast.makeText(this, "Download fehlgeschlagen keine lokale Datenbank vorhanden", Toast.LENGTH_LONG).show()
// Zurück zum Login, damit man es erneut probieren kann
showLoginThenDownload()
return@downloadAndReplaceDatabase
}
if (!ok) {
Toast.makeText(this, "Download fehlgeschlagen arbeite offline mit vorhandener DB", Toast.LENGTH_LONG).show()
}
// Opening-Screen starten
openingScreenHandler = HandlerOpeningScreen(this)
openingScreenHandler.init()
openingScreenHandler.refreshHeaderStatusLive()
}
},
onError = { msg ->
showBusy(false)
Toast.makeText(this, msg, Toast.LENGTH_LONG).show()
showLoginThenDownload()
}
)
}
.setNegativeButton("Beenden") { _, _ -> finishAffinity() }
.create()
dialog.show()
}
private fun showBusy(show: Boolean) {
if (show) {
if (progress == null) {
progress = ProgressBar(this).apply {
isIndeterminate = true
(window?.decorView as? android.view.ViewGroup)?.addView(this)
}
}
progress?.visibility = View.VISIBLE
} else {
progress?.visibility = View.GONE
}
}
private fun dp(v: Int): Int = (v * resources.displayMetrics.density).toInt()
// --- LIVE NETZSTATUS (optional, für deine Status-Leiste) ---
override fun onResume() {
super.onResume()
registerNetworkCallback()
if (::openingScreenHandler.isInitialized && !isInQuestionnaire) {
openingScreenHandler.refreshHeaderStatusLive()
}
}
override fun onPause() {
super.onPause()
unregisterNetworkCallback()
}
private fun registerNetworkCallback() {
if (netCb != null) return
val cm = getSystemService(ConnectivityManager::class.java)
val req = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()
netCb = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
runOnUiThread {
if (::openingScreenHandler.isInitialized && !isInQuestionnaire) {
openingScreenHandler.refreshHeaderStatusLive()
}
}
}
override fun onLost(network: Network) {
runOnUiThread {
if (::openingScreenHandler.isInitialized && !isInQuestionnaire) {
openingScreenHandler.refreshHeaderStatusLive()
}
}
}
override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) {
runOnUiThread {
if (::openingScreenHandler.isInitialized && !isInQuestionnaire) {
openingScreenHandler.refreshHeaderStatusLive()
}
}
}
}
cm.registerNetworkCallback(req, netCb!!)
}
private fun unregisterNetworkCallback() {
val cb = netCb ?: return
val cm = getSystemService(ConnectivityManager::class.java)
cm.unregisterNetworkCallback(cb)
netCb = null
}
// --- /LIVE NETZSTATUS ---
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
}
fun startQuestionnaire(questionnaire: QuestionnaireBase<*>, languageID: String) {
isInQuestionnaire = true
isFirstQuestionnairePage = true
questionnaire.attach(this, languageID)
questionnaire.startQuestionnaire()
}
override fun onBackPressed() {
if (!::openingScreenHandler.isInitialized || !openingScreenHandler.onBackPressed()) {
super.onBackPressed()
}
}
fun finishQuestionnaire() {
isInQuestionnaire = false
isFirstQuestionnairePage = false
if (::openingScreenHandler.isInitialized) {
openingScreenHandler.init()
}
}
}