fix(kiosk): gateway install hardening + diagnostic dialog on failure
- installApk(): add runtime canRequestPackageInstalls() check with user dialog (permission may have been revoked or not active even if declared in manifest) - STATUS_FAILURE else branch: show AlertDialog with full diagnostics on screen (status code, message, APK size, Android version, device model) so the problem is visible even when the server error report fails to deliver - Dialog has Riprova button (retries installWithPackageInstaller immediately) and Salta button (skips to gateway status check) - INSTALL_PERM_REQUEST onActivityResult: resume from installApk() if a local APK file is already present, not just from triggerApkDownload() - ErrorReporter context enriched with device model string
This commit is contained in:
@@ -817,6 +817,23 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
file.delete()
|
file.delete()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Double-check install permission at runtime (may have been revoked or not granted yet)
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !packageManager.canRequestPackageInstalls()) {
|
||||||
|
AlertDialog.Builder(this)
|
||||||
|
.setTitle("⚠️ Permesso mancante")
|
||||||
|
.setMessage("Per installare il Gateway è necessario abilitare \"Installa app sconosciute\" per questa app.\n\nTocca OK per aprire le impostazioni.")
|
||||||
|
.setPositiveButton("OK") { _, _ ->
|
||||||
|
pendingInstallFile = file
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
startActivityForResult(
|
||||||
|
Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES, Uri.parse("package:$packageName")),
|
||||||
|
INSTALL_PERM_REQUEST
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.setNegativeButton("Annulla", null)
|
||||||
|
.show()
|
||||||
|
return
|
||||||
|
}
|
||||||
installWithPackageInstaller(file, GATEWAY_PACKAGE)
|
installWithPackageInstaller(file, GATEWAY_PACKAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -897,6 +914,14 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
val msg = intent?.getStringExtra(
|
val msg = intent?.getStringExtra(
|
||||||
android.content.pm.PackageInstaller.EXTRA_STATUS_MESSAGE
|
android.content.pm.PackageInstaller.EXTRA_STATUS_MESSAGE
|
||||||
) ?: "status=$status"
|
) ?: "status=$status"
|
||||||
|
val diagInfo = buildString {
|
||||||
|
appendLine("Status: $status")
|
||||||
|
appendLine("Msg: $msg")
|
||||||
|
appendLine("PKG: $targetPkg")
|
||||||
|
appendLine("APK: ${file.length() / 1024} KB")
|
||||||
|
appendLine("Android: ${Build.VERSION.SDK_INT} (${Build.VERSION.RELEASE})")
|
||||||
|
appendLine("Device: ${Build.MANUFACTURER} ${Build.MODEL}")
|
||||||
|
}
|
||||||
setGatewayUI("❌", getString(R.string.install_error_install),
|
setGatewayUI("❌", getString(R.string.install_error_install),
|
||||||
msg, 0xFFf87171.toInt())
|
msg, 0xFFf87171.toInt())
|
||||||
ErrorReporter.reportMessage(
|
ErrorReporter.reportMessage(
|
||||||
@@ -907,13 +932,30 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
"status" to status,
|
"status" to status,
|
||||||
"msg" to msg,
|
"msg" to msg,
|
||||||
"apk_kb" to (file.length() / 1024),
|
"apk_kb" to (file.length() / 1024),
|
||||||
"android" to Build.VERSION.SDK_INT
|
"android" to Build.VERSION.SDK_INT,
|
||||||
|
"device" to "${Build.MANUFACTURER} ${Build.MODEL}"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val pkgInstalled = try {
|
val pkgInstalled = try {
|
||||||
packageManager.getPackageInfo(targetPkg, 0); true
|
packageManager.getPackageInfo(targetPkg, 0); true
|
||||||
} catch (_: Exception) { false }
|
} catch (_: Exception) { false }
|
||||||
if (pkgInstalled) runOnUiThread { offerUninstallAndRetry(file, targetPkg) }
|
runOnUiThread {
|
||||||
|
if (pkgInstalled) {
|
||||||
|
offerUninstallAndRetry(file, targetPkg)
|
||||||
|
} else {
|
||||||
|
// Show diagnostic dialog with Retry button
|
||||||
|
AlertDialog.Builder(this@SetupActivity)
|
||||||
|
.setTitle("❌ Installazione fallita (status=$status)")
|
||||||
|
.setMessage(diagInfo.trim())
|
||||||
|
.setPositiveButton("Riprova") { _, _ ->
|
||||||
|
installWithPackageInstaller(file, targetPkg)
|
||||||
|
}
|
||||||
|
.setNeutralButton("Salta") { _, _ ->
|
||||||
|
checkGatewayStatus()
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1012,7 +1054,15 @@ class SetupActivity : AppCompatActivity() {
|
|||||||
super.onActivityResult(requestCode, resultCode, data)
|
super.onActivityResult(requestCode, resultCode, data)
|
||||||
when (requestCode) {
|
when (requestCode) {
|
||||||
INSTALL_PERM_REQUEST -> {
|
INSTALL_PERM_REQUEST -> {
|
||||||
if (pendingApkDownloadUrl.isNotEmpty()) triggerApkDownload(pendingApkDownloadUrl)
|
// Returned from "Install unknown apps" settings for this app.
|
||||||
|
// pendingInstallFile is set when coming from installApk() permission check,
|
||||||
|
// pendingApkDownloadUrl is set when coming from triggerApkDownload().
|
||||||
|
val pendingFile = pendingInstallFile
|
||||||
|
if (pendingFile != null && pendingFile.exists()) {
|
||||||
|
installApk(pendingFile)
|
||||||
|
} else if (pendingApkDownloadUrl.isNotEmpty()) {
|
||||||
|
triggerApkDownload(pendingApkDownloadUrl)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
INSTALL_CONFIRM_REQUEST -> {
|
INSTALL_CONFIRM_REQUEST -> {
|
||||||
// On Android 11+ the final install result (STATUS_SUCCESS / STATUS_FAILURE)
|
// On Android 11+ the final install result (STATUS_SUCCESS / STATUS_FAILURE)
|
||||||
|
|||||||
Reference in New Issue
Block a user