diff --git a/evershelf-kiosk/app/build.gradle.kts b/evershelf-kiosk/app/build.gradle.kts
index 3321b1d..ea19834 100644
--- a/evershelf-kiosk/app/build.gradle.kts
+++ b/evershelf-kiosk/app/build.gradle.kts
@@ -11,8 +11,8 @@ android {
applicationId = "it.dadaloop.evershelf.kiosk"
minSdk = 24
targetSdk = 34
- versionCode = 7
- versionName = "1.5.1"
+ versionCode = 8
+ versionName = "1.5.2"
}
signingConfigs {
diff --git a/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/KioskActivity.kt b/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/KioskActivity.kt
index 3dc50e3..079a7a6 100644
--- a/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/KioskActivity.kt
+++ b/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/KioskActivity.kt
@@ -439,11 +439,10 @@ class KioskActivity : AppCompatActivity() {
}
private fun applyScreensaverFlag() {
- if (prefs.getBoolean(KEY_SCREENSAVER, false)) {
- window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
- } else {
- window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
- }
+ // The kiosk screen must ALWAYS stay on — the in-app screensaver is a JS overlay
+ // (clock + info) shown by the webapp after inactivity, not an Android screen timeout.
+ // Never clear FLAG_KEEP_SCREEN_ON regardless of the screensaver preference.
+ window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
// ── Inject kiosk overlay (exit + refresh buttons) ────────────────────
diff --git a/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/SettingsActivity.kt b/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/SettingsActivity.kt
index 86c4452..a53e5ff 100644
--- a/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/SettingsActivity.kt
+++ b/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/SettingsActivity.kt
@@ -106,12 +106,24 @@ class SettingsActivity : AppCompatActivity() {
.putString(KEY_URL, url)
.putBoolean(KEY_SCREENSAVER, screensaverOn)
.apply()
- // Apply FLAG_KEEP_SCREEN_ON immediately based on new setting
- if (screensaverOn) {
- window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
- } else {
- window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
- }
+ // Screen always stays on in kiosk mode — no FLAG_KEEP_SCREEN_ON change needed here.
+ // Push screensaver preference to the webapp so the in-app clock overlay is toggled.
+ Thread {
+ try {
+ val apiUrl = "$url/api/index.php?action=save_settings"
+ val body = "{\"screensaver_enabled\":$screensaverOn}"
+ val conn = (java.net.URL(apiUrl).openConnection() as java.net.HttpURLConnection).apply {
+ requestMethod = "POST"
+ setRequestProperty("Content-Type", "application/json")
+ connectTimeout = 5000
+ readTimeout = 5000
+ doOutput = true
+ }
+ conn.outputStream.use { it.write(body.toByteArray()) }
+ conn.inputStream.close()
+ conn.disconnect()
+ } catch (_: Exception) {}
+ }.start()
Toast.makeText(this, "Impostazioni salvate", Toast.LENGTH_SHORT).show()
finish()
}
diff --git a/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/SetupActivity.kt b/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/SetupActivity.kt
index 119bbca..c217c86 100644
--- a/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/SetupActivity.kt
+++ b/evershelf-kiosk/app/src/main/kotlin/it/dadaloop/evershelf/kiosk/SetupActivity.kt
@@ -1068,31 +1068,35 @@ class SetupActivity : AppCompatActivity() {
private fun finishSetup() {
prefs.edit().putBoolean(KEY_SETUP_COMPLETE, true).apply()
- // ── Pre-configure Scale Gateway URL in webapp settings ──────────────────
- // If the user has a scale and the gateway is installed, write the WebSocket
- // URL and enable the scale in the webapp's server settings (.env via API)
- // so the webapp works out-of-the-box without manual settings configuration.
- if (prefs.getBoolean(KEY_HAS_SCALE, false) && isGatewayInstalled()) {
- val baseUrl = (prefs.getString(KEY_URL, "") ?: "").trimEnd('/')
- if (baseUrl.isNotEmpty()) {
- val gwUrl = "ws://127.0.0.1:8765"
- Thread {
- try {
- val url = "$baseUrl/api/index.php?action=save_settings"
- val body = """{"scale_enabled":true,"scale_gateway_url":"$gwUrl"}"""
- val conn = (java.net.URL(url).openConnection() as java.net.HttpURLConnection).apply {
- requestMethod = "POST"
- setRequestProperty("Content-Type", "application/json")
- connectTimeout = 5000
- readTimeout = 5000
- doOutput = true
+ // ── Sync settings to webapp API ─────────────────────────────────────────
+ // Always push: screensaver_enabled (in-app clock overlay preference).
+ // Conditionally add: scale settings when gateway is installed.
+ val baseUrl = (prefs.getString(KEY_URL, "") ?: "").trimEnd('/')
+ if (baseUrl.isNotEmpty()) {
+ val hasScale = prefs.getBoolean(KEY_HAS_SCALE, false) && isGatewayInstalled()
+ val screensaver = prefs.getBoolean(KEY_SCREENSAVER, false)
+ Thread {
+ try {
+ val url = "$baseUrl/api/index.php?action=save_settings"
+ val body = buildString {
+ append("{\"screensaver_enabled\":$screensaver")
+ if (hasScale) {
+ append(",\"scale_enabled\":true,\"scale_gateway_url\":\"ws://127.0.0.1:8765\"")
}
- conn.outputStream.use { it.write(body.toByteArray()) }
- conn.inputStream.close()
- conn.disconnect()
- } catch (_: Exception) {}
- }.start()
- }
+ append("}")
+ }
+ val conn = (java.net.URL(url).openConnection() as java.net.HttpURLConnection).apply {
+ requestMethod = "POST"
+ setRequestProperty("Content-Type", "application/json")
+ connectTimeout = 5000
+ readTimeout = 5000
+ doOutput = true
+ }
+ conn.outputStream.use { it.write(body.toByteArray()) }
+ conn.inputStream.close()
+ conn.disconnect()
+ } catch (_: Exception) {}
+ }.start()
}
setResult(RESULT_OK)
finish()
@@ -1148,7 +1152,33 @@ class SetupActivity : AppCompatActivity() {
getString(R.string.install_success_detail), 0xFF34d399.toInt(), btnEnabled = false)
Handler(Looper.getMainLooper()).postDelayed({ checkGatewayStatus() }, 1500)
} else {
- checkGatewayStatus()
+ // Install failed or user cancelled. Show an explicit retry button
+ // that re-launches the system installer directly (skipping PackageInstaller,
+ // which is known to give STATUS=1 on this device).
+ val retryFile = pendingInstallFile
+ val retryPkg = pendingInstallPkg
+ setGatewayUI(
+ "⚠️",
+ "Installazione non completata",
+ "L'app non risulta installata. Premi il pulsante sotto per riprovare.",
+ 0xFFfbbf24.toInt()
+ )
+ btnInstallGateway.visibility = View.VISIBLE
+ btnInstallGateway.text = "🔄 Riprova installazione"
+ btnInstallGateway.setOnClickListener {
+ // Reset button back to default before retrying
+ btnInstallGateway.text = "📥 Installa Scale Gateway"
+ btnInstallGateway.setOnClickListener {
+ pendingApkDownloadUrl = GATEWAY_DOWNLOAD_URL
+ triggerApkDownload(GATEWAY_DOWNLOAD_URL)
+ }
+ if (retryFile != null && retryFile.exists()) {
+ tryFallbackInstall(retryFile, retryPkg)
+ } else {
+ pendingApkDownloadUrl = GATEWAY_DOWNLOAD_URL
+ triggerApkDownload(GATEWAY_DOWNLOAD_URL)
+ }
+ }
}
}, 800)
}
@@ -1162,7 +1192,9 @@ class SetupActivity : AppCompatActivity() {
)
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, "application/vnd.android.package-archive")
- flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK
+ // Note: do NOT add FLAG_ACTIVITY_NEW_TASK — it breaks startActivityForResult:
+ // Android would return RESULT_CANCELED immediately without waiting for the user.
+ flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
}
pendingInstallFile = file
pendingInstallPkg = targetPkg
diff --git a/evershelf-kiosk/app/src/main/res/layout/activity_setup.xml b/evershelf-kiosk/app/src/main/res/layout/activity_setup.xml
index 2360e06..d95d274 100644
--- a/evershelf-kiosk/app/src/main/res/layout/activity_setup.xml
+++ b/evershelf-kiosk/app/src/main/res/layout/activity_setup.xml
@@ -985,7 +985,7 @@
android:id="@+id/tvScreensaverDesc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="Mostra un orologio con fatti utili dopo 5 minuti di inattività. Di default è disattivato (lo schermo resta sempre acceso)."
+ android:text="Dopo 5 minuti di inattività mostra un overlay con l'orologio e informazioni utili (statistiche, piano pasti). Lo schermo rimane SEMPRE acceso — questa opzione riguarda solo l'overlay visivo in-app."
android:textColor="#94a3b8"
android:textSize="15sp"
android:gravity="center"
diff --git a/evershelf-kiosk/app/src/main/res/values/strings.xml b/evershelf-kiosk/app/src/main/res/values/strings.xml
index f51f91c..940abab 100644
--- a/evershelf-kiosk/app/src/main/res/values/strings.xml
+++ b/evershelf-kiosk/app/src/main/res/values/strings.xml
@@ -59,10 +59,10 @@
Server not reachable ⚠️
Install errors won\'t reach GitHub Issues. Check the URL entered in step 2.
- Screensaver
+ Salvaschermo in-app
Shows a clock with useful facts after 5 minutes of inactivity. Off by default (screen stays always on).
- Enable screensaver
- If disabled, the screen stays always on.
+ Abilita salvaschermo orologio
+ Mostra l'overlay orologio dopo 5 min. Lo schermo resta sempre acceso.
Language