App 2.19.5: the installer screen fallback reads the APK
The car refuses the silent session for a non-system app; the fallback installer screen could not read our FileProvider URI because grants from the system user are refused. The car build now hands it a file URI to the verified copy in Downloads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LhzAVaUyqcw5PkGjz4mWW6
This commit is contained in:
@@ -71,7 +71,9 @@ version, checks it against the `.sha256`, checks the package, and installs it wi
|
||||
installer session as an over-the-air update. The car build only; the stable build has no button.
|
||||
|
||||
On the Android 9 emulator (car build, system user) this installed without asking, from the
|
||||
storage's top folder; on the car the stick's top folder is used the same way.
|
||||
storage's top folder; on the car the stick's top folder is used the same way, and the install
|
||||
ends on Android's installer screen, confirmed with **Install** (below). Every step, with the
|
||||
platform's own words, is on the Logs tab under "Updates".
|
||||
|
||||
## When it says something else
|
||||
|
||||
@@ -100,5 +102,11 @@ path: the app opens the archive itself and streams it in. The approach comes fro
|
||||
the same wall on the same hardware. Upstream later fell back to "download to Downloads and
|
||||
tap it"; this fork tries the session first and keeps that as the fallback.
|
||||
|
||||
**Not yet tried on this car:** whether the session installs silently as the system user, or
|
||||
asks for a confirmation.
|
||||
**On the car (SWI68, 2026-10-23) the session is refused:** the package manager answers
|
||||
`Not allowed to install non-system apps on internal storage` — a firmware policy for apps that
|
||||
are not system apps, even when they run as the system user. The app then opens Android's own
|
||||
installer screen, where the driver confirms with **Install**, the same route the Files app takes.
|
||||
That screen needs a `file://` URI on the car build: a read grant on our FileProvider is refused
|
||||
when it comes from the system user (`not exported from UID 1000`), and the installer reports the
|
||||
unreadable file as "There was a problem parsing the package". On the emulator the session still
|
||||
installs silently.
|
||||
|
||||
@@ -118,6 +118,14 @@ tyre pressures, GPS (lat, lon, elevation, heading) and the is_* flags. It does *
|
||||
confirmed car facts, app structure, UI conventions, build/test/ship, documents. It replaces
|
||||
upstream's EVABRPUploader text. The test emulator is now in the flake: `nix run .#car-emulator`
|
||||
(Android 9 AOSP at 1920×720, 160 dpi; the car build installs as the system user — checked).
|
||||
- 2026-10-23 — App 2.19.5: installing from USB (and over the air) works on the car again, with a
|
||||
confirmation. The update log showed the car refusing the silent session: `Not allowed to install
|
||||
non-system apps on internal storage`. The fallback, Android's installer screen, then said "There
|
||||
was a problem parsing the package": as the system user, our FileProvider's read grant to the
|
||||
installer is refused (`not exported from UID 1000`). The car build now hands the installer a
|
||||
file URI to the verified copy in Downloads (StrictMode's file-URI check lifted for that one
|
||||
call). On the emulator, with the session forced to fail as on the car, the installer screen
|
||||
asked to update and installed it. Not tried on the car yet. OTA.md updated.
|
||||
- 2026-10-23 — App 2.19.4: "Export CarPlay data" on the Logs tab (Foreground apps card), for the
|
||||
question whether CarPlay's resolution can change. CarPlay with policy_control still leaves a grey
|
||||
strip, also after reconnecting: Allgo announces a smaller picture to the iPhone. 20 s after the
|
||||
|
||||
+2
-2
@@ -34,8 +34,8 @@ android {
|
||||
applicationId "com.stinnesbeck.nilsmg4"
|
||||
minSdk 27
|
||||
targetSdk 36
|
||||
versionCode 103
|
||||
versionName "2.19.4"
|
||||
versionCode 104
|
||||
versionName "2.19.5"
|
||||
|
||||
// Nothing about the server ships in the APK: its URL and ingest token are entered in
|
||||
// the app's Server tab (ServerConfig), and the database is only reachable by the server.
|
||||
|
||||
@@ -566,6 +566,28 @@ final class OtaUpdater {
|
||||
}
|
||||
|
||||
File publicApk = copyToPublicDownloads(apk);
|
||||
if (android.os.Process.myUid() == android.os.Process.SYSTEM_UID) {
|
||||
// As the system user, our FileProvider's read grant is refused ("not exported from
|
||||
// UID 1000") and the installer reports the unreadable file as a parse error. A file
|
||||
// URI it reads with its own storage permission instead, as from the Files app.
|
||||
Intent install = new Intent(Intent.ACTION_VIEW)
|
||||
.setDataAndType(Uri.fromFile(publicApk), "application/vnd.android.package-archive")
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
if (install.resolveActivity(context.getPackageManager()) == null) {
|
||||
throw new IllegalStateException("No package installer activity");
|
||||
}
|
||||
// StrictMode forbids file URIs in intents (FileUriExposedException): lifted for this
|
||||
// one call only.
|
||||
android.os.StrictMode.VmPolicy policy = android.os.StrictMode.getVmPolicy();
|
||||
android.os.StrictMode.setVmPolicy(new android.os.StrictMode.VmPolicy.Builder().build());
|
||||
try {
|
||||
context.startActivity(install);
|
||||
} finally {
|
||||
android.os.StrictMode.setVmPolicy(policy);
|
||||
}
|
||||
Log.i(TAG, "System install UI opened with a file URI for " + publicApk.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
Uri contentUri = FileProvider.getUriForFile(context,
|
||||
context.getPackageName() + ".fileprovider", publicApk);
|
||||
Intent install = new Intent(Intent.ACTION_VIEW)
|
||||
|
||||
Reference in New Issue
Block a user