Scan the enrollment QR in-app instead of relying on the camera app

Not every phone's camera app hands a scanned aiapp:// URI off to the app
reliably, which made enrollment an annoying multi-step process. The
Settings screen now scans the QR itself via zxing-android-embedded's
ScanContract (offline, no Play Services/ML Kit download) and feeds the
decoded URI through the existing parseEnrollmentUri. The aiapp://enroll
deep link stays as a fallback for cameras that do redirect.

Verified on the emulator: Scan QR code launches the scanner, prompts for
camera permission, shows a live preview, and backing out returns to
Settings cleanly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017xn8nHw1tw1R6PtiY1eEtw
This commit is contained in:
irisandClaude Sonnet 5 committed 2026-08-25 16:25:14 -04:00
1 parent 99bcc341c1
commit da2c110429
5 files changed
+56 -13

No files matched your search

+10 -4
View File
@@ -334,10 +334,16 @@ complete path out of everything spawning one created.
ANSI), encoding `aiapp://enroll?host=…&port=…&token=…`. The CA stays
embedded in the APK (`PinnedCert.kt` pattern), so the QR carries no
trust material — photographing the terminal leaks only the token
(rotatable), never a way to weaken pinning. The app side needs no QR
library at all: it registers an intent filter for the `aiapp://enroll`
scheme, and the stock camera app hands the scanned URI straight to
`MainActivity` (2026-08-24).
(rotatable), never a way to weaken pinning. The app registers an intent
filter for the `aiapp://enroll` scheme as a fallback, for a camera app
that redirects a scanned URI straight to `MainActivity` (2026-08-24).
That was meant to be the only path — "the app side needs no QR library
at all" — but reversed the same day: not every phone's stock camera
redirects a scanned URI to an app reliably, so the Settings screen also
scans in-app via `zxing-android-embedded`'s `ScanContract` (a ready-made
scanner Activity reached through the AndroidX Activity Result API,
fully offline, no Play Services/ML Kit model download) and feeds the
decoded URI to the same `parseEnrollmentUri` (2026-08-25).
- **Storage**: server keeps only the SHA-256 in `config.json` (plain hash
is enough for high-entropy random input; buys that a leaked config
doesn't leak the credential). No "show token again" — lost means rotate.