fix: 'Aggiorna ora' banner + APK conflict auto-retry after uninstall
Webapp update banner: - 'Vedi novità' link replaced with 'Aggiorna ora' button - Clicking 'Aggiorna ora' does a hard page reload (?bust=timestamp) which forces the browser to fetch the latest files from the server - GitHub release URL kept as a small secondary 'novità' link APK install conflict (kiosk + scale gateway): - STATUS_PENDING_USER_ACTION: changed startActivity → startActivityForResult (kiosk) / installConfirmLauncher.launch (gateway) so we get notified if the system installer fails due to signature conflict - On non-OK result from system installer: show AlertDialog offering to uninstall, using UNINSTALL_REQUEST / uninstallLauncher - STATUS_FAILURE_CONFLICT/INCOMPATIBLE: same uninstall flow - After uninstall completes, install automatically retries with the saved APK file (pendingInstallFile) — no manual re-download needed - Gateway: also saves destFile to pendingInstallFile at download time
This commit is contained in:
@@ -83,6 +83,8 @@ class KioskActivity : AppCompatActivity() {
|
||||
private lateinit var btnInstallUpdate: MaterialButton
|
||||
private lateinit var btnDismissUpdate: MaterialButton
|
||||
private var pendingApkDownloadUrl: String = ""
|
||||
private var pendingInstallFile: java.io.File? = null
|
||||
private var pendingInstallPkg: String = ""
|
||||
|
||||
// Triple-tap to exit
|
||||
private var tapCount = 0
|
||||
@@ -99,6 +101,8 @@ class KioskActivity : AppCompatActivity() {
|
||||
private const val FILE_CHOOSER_REQUEST = 1002
|
||||
private const val PERMISSION_REQUEST_CODE = 1003
|
||||
private const val INSTALL_PERM_REQUEST = 1004 // ACTION_MANAGE_UNKNOWN_APP_SOURCES
|
||||
private const val INSTALL_CONFIRM_REQUEST = 1005 // system installer confirm dialog
|
||||
private const val UNINSTALL_REQUEST = 1006 // ACTION_DELETE → auto-retry install
|
||||
private const val PREFS_NAME = "evershelf_kiosk"
|
||||
private const val KEY_URL = "evershelf_url"
|
||||
private const val KEY_SETUP_COMPLETE = "setup_complete"
|
||||
@@ -869,25 +873,34 @@ class KioskActivity : AppCompatActivity() {
|
||||
) ?: android.content.pm.PackageInstaller.STATUS_FAILURE
|
||||
when (status) {
|
||||
android.content.pm.PackageInstaller.STATUS_PENDING_USER_ACTION -> {
|
||||
// Android needs user confirmation — launch the system dialog
|
||||
// Android needs user confirmation — use startActivityForResult so we
|
||||
// get notified if the system installer fails (e.g. signature conflict)
|
||||
@Suppress("DEPRECATION")
|
||||
val confirmIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
|
||||
intent?.getParcelableExtra(Intent.EXTRA_INTENT, Intent::class.java)
|
||||
else intent?.getParcelableExtra(Intent.EXTRA_INTENT)
|
||||
if (confirmIntent != null) startActivity(confirmIntent)
|
||||
if (confirmIntent != null) {
|
||||
pendingInstallFile = file
|
||||
pendingInstallPkg = targetPkg
|
||||
startActivityForResult(confirmIntent, INSTALL_CONFIRM_REQUEST)
|
||||
}
|
||||
}
|
||||
android.content.pm.PackageInstaller.STATUS_SUCCESS ->
|
||||
runOnUiThread { Toast.makeText(this@KioskActivity, "✅ Aggiornamento installato", Toast.LENGTH_SHORT).show() }
|
||||
android.content.pm.PackageInstaller.STATUS_FAILURE_INCOMPATIBLE,
|
||||
android.content.pm.PackageInstaller.STATUS_FAILURE_CONFLICT -> {
|
||||
// Signature mismatch: offer to uninstall the old version first
|
||||
// Signature mismatch: offer to uninstall; on return auto-retry install
|
||||
runOnUiThread {
|
||||
pendingInstallFile = file
|
||||
pendingInstallPkg = targetPkg
|
||||
androidx.appcompat.app.AlertDialog.Builder(this@KioskActivity)
|
||||
.setTitle("⚠️ Conflitto firma APK")
|
||||
.setMessage("L'app installata usa una firma diversa.\n\nDevi disinstallare la versione precedente e poi ripremere Scarica.")
|
||||
.setMessage("L'app installata usa una firma diversa.\n\nDisinstalla la versione precedente: al termine l'installazione riparte automaticamente.")
|
||||
.setPositiveButton("Disinstalla") { _, _ ->
|
||||
startActivity(Intent(Intent.ACTION_DELETE,
|
||||
android.net.Uri.parse("package:$targetPkg")))
|
||||
startActivityForResult(
|
||||
Intent(Intent.ACTION_DELETE, android.net.Uri.parse("package:$targetPkg")),
|
||||
UNINSTALL_REQUEST
|
||||
)
|
||||
}
|
||||
.setNegativeButton("Annulla", null)
|
||||
.show()
|
||||
@@ -1002,6 +1015,35 @@ class KioskActivity : AppCompatActivity() {
|
||||
val url = pendingApkDownloadUrl
|
||||
if (url.isNotEmpty()) triggerApkDownload(url)
|
||||
}
|
||||
// System installer returned: if not OK the install failed (possibly signature conflict).
|
||||
// Show a dialog offering to uninstall the old version so the user can retry.
|
||||
if (requestCode == INSTALL_CONFIRM_REQUEST && resultCode != RESULT_OK) {
|
||||
val f = pendingInstallFile
|
||||
val pkg = pendingInstallPkg
|
||||
if (f != null && f.exists() && pkg.isNotEmpty()) {
|
||||
runOnUiThread {
|
||||
androidx.appcompat.app.AlertDialog.Builder(this)
|
||||
.setTitle("⚠️ Installazione non riuscita")
|
||||
.setMessage("Se hai visto un errore di conflitto firma, devi disinstallare la versione precedente.\n\nDisinstalla ora? L'installazione ripartirà automaticamente.")
|
||||
.setPositiveButton("Disinstalla") { _, _ ->
|
||||
startActivityForResult(
|
||||
Intent(Intent.ACTION_DELETE, android.net.Uri.parse("package:$pkg")),
|
||||
UNINSTALL_REQUEST
|
||||
)
|
||||
}
|
||||
.setNegativeButton("Annulla", null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
// Returned from uninstall screen — auto-retry the install with the saved APK file.
|
||||
if (requestCode == UNINSTALL_REQUEST) {
|
||||
val f = pendingInstallFile
|
||||
val pkg = pendingInstallPkg
|
||||
if (f != null && f.exists() && pkg.isNotEmpty()) {
|
||||
installWithPackageInstaller(f, pkg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
||||
Reference in New Issue
Block a user