-
released this
2026-11-10 00:57:02 +00:00 | 0 commits to main since this releaseQQQ Mobile 1.0.4 (versionCode 6): Release notes
Signed APK for direct installation over USB (
adb install -r) or MDM. It updates 1.0.3, 1.0.2, 1.0.1 and 1.0.0 in place because the signer is the same; do not uninstall first.Install steps: INSTALL.md (Windows laptop, USB, adb).
Artifact
Item Value Application ID io.qrun.mobile.scannerVersion 1.0.4 / versionCode 6 (min Android 8.0 / API 26, target API 35) File QQQ-Mobile-1.0.4.apk, 15015419 bytesAPK SHA-256 F643872F4435B55F6A0B929D1762CAACB18010E5CC0B473C7B4BABBDC4299489Signer certificate SHA-256 BDDB2D2F45A5925C643A83ABAF616C1EAB2387DC5CDA7B645A6F4C0D5B17A9FFSigning Existing permanent QRun release key ( CN=QQQ Mobile, OU=Android, O=QRunIO), APK signature schemes v2 + v3, one signer. No new key.Source mainat9bae976138c4447f3fa451ee49b8585e80f01847(treebb70c3128f4c7c10cac73973d96f02f3ac5ce9c9, tagscanner-v1.0.4): 1.0.3 source plus Android PR 26 and PR 27.The checksum proves file integrity only. Separately verify the signing certificate; only the same signer permits in-place updates.
What 1.0.4 changes
- Metadata load timeout: loading the server's metadata no longer fails with "Error loading QInstance: timeout" on a handheld. The metadata response is large (about 1.7 MB uncompressed for an administrator) and can take the server several seconds to build, so the default 10 second read timeout expired. That one call now allows 60 seconds; every other call keeps its short timeout. A timeout now reads "Timed out after 60.0s loading the server's metadata from /qqq/v1/metaData". (PR 26)
- Sign-out ends the identity-provider session: Sign out now also ends the identity-provider session in the browser when the server supports it, and every browser sign-in sends
max_age=0next toprompt=login. Before, ordinary Sign out cleared only the QQQ session, so the provider session left in the browser silently signed the same person straight back in. Servers without provider logout still get local plus QQQ sign-out. (PR 27) - Includes 1.0.3 (versionCode 5): string widget icons and summary-only help content from current QQQ core are accepted. (PR 24)
Verification of this file
Checked on the published file before upload and again on the copy downloaded back from this release:
- SHA-256 equals the value above.
aapt2 dump badging:versionCode='6' versionName='1.0.4', packageio.qrun.mobile.scanner.apksigner verify --print-certs: verifies with v2 and v3, exactly one signer, certificate SHA-256 as above.- The compiled code contains the new metadata timeout message ("Timed out after ... loading the server's metadata from"), which is absent from the 1.0.3 APK.
Qualification status of this build
- Hosted CI on the tagged commit (run 7323): checkout, set-up and the Gradle step (source checks, JVM unit tests, scanner lint, debug and QA assembly) passed. The emulator test step did not run because the runner that picked up the job has no usable
/dev/kvm; that is a runner limitation, not a test failure. The PR 26 commit passed the full job including emulator tests (run 7319). The PR 27 commit has not had an emulator run. - Devices: at publication, 1.0.4 had not yet been installed on a handheld. Confirm the in-place update and the two fixes on the first device before rolling out to the rest.
- This is published as a prerelease like the earlier scanner releases, because device qualification is by the operator.
Compatibility
- Same signer and a higher versionCode: in-place update that keeps login, server address and enrollment. Development-signed (debug/demo) installs have a different signer and are refused; that needs an explicit, owner-approved migration.
- Release builds reject HTTP; use trusted HTTPS only.
- Server needs the semantic UI API (core 1.8+; OAuth2 sign-in needs 1.10) and
mobile-scanners1.1+ (1.6.0+ to record heartbeat versions). - Online only; no offline queue.
Downloads
-
QQQ Mobile scanner 1.0.2 (versionCode 4) — signed candidate
Pre-ReleaseQRun-IO/ci-policy: ci / fork-guard (push) SkippedQRun-IO/ci-policy: native / fork-deny (push) SkippedQRun-IO/ci-policy: native / dotnet-0 (push) SkippedQRun-IO/ci-policy: ci / head-profile (push) SkippedQRun-IO/ci-policy: ci / repository-policy (push) SkippedQRun-IO/ci-policy: ci / application-template-0 (push) SkippedQRun-IO/ci-policy: ci / gradle-1 (push) SkippedQRun-IO/ci-policy: ci / java-core-2-head (push) SkippedQRun-IO/ci-policy: ci / java-docker-3 (push) SkippedQRun-IO/ci-policy: ci / java-docker-3-head (push) SkippedQRun-IO/ci-policy: ci / java-docker-4 (push) SkippedQRun-IO/ci-policy: ci / java-frontend-browser-5 (push) SkippedQRun-IO/ci-policy: ci / java-maven-6 (push) SkippedQRun-IO/ci-policy: ci / java-maven-6-head (push) SkippedQRun-IO/ci-policy: ci / java-maven-7 (push) SkippedQRun-IO/ci-policy: native / native-result (push) Successful in 10sQRun-IO/ci-policy: ci / java-maven-7-head (push) SkippedQRun-IO/ci-policy: ci / node-8 (push) SkippedQRun-IO/ci-policy: ci / node-9 (push) SkippedQRun-IO/ci-policy: ci / node-10 (push) SkippedQRun-IO/ci-policy: ci / node-playwright-11 (push) SkippedQRun-IO/ci-policy: ci / repository-policy-12 (push) SkippedQRun-IO/ci-policy: ci / source-config-13 (push) SkippedQRun-IO/ci-policy: ci / source-config-14 (push) SkippedQRun-IO/ci-policy: ci / original-business (push) SkippedQRun-IO/ci-policy: ci / original-mcp (push) SkippedQRun-IO/ci-policy: ci / original-voyage (push) SkippedQRun-IO/ci-policy: ci / original-cli (push) SkippedQRun-IO/ci-policy: ci / not-enrolled (push) SkippedQRun-IO/ci-policy: ci / Scoped workflow [workflow 9cb8c13124a99d18da83cbcd4faa795859ac9e55] (push) Successful in 12sQRun-IO/ci-policy: ci / shared-pipeline (push) SkippedShared Android CI / unit-test (push) Successful in 4m28sShared Android CI / android-test (push) Successful in 10m14sShared Android CI / secrets (push) Successful in 21sQRun-IO/ci-policy: Shared Android CI / unit-test (push) Successful in 4m1sQRun-IO/ci-policy: Shared Android CI / android-test (push) Successful in 9m50sQRun-IO/ci-policy: Shared Android CI / secrets (push) Successful in 21sShared Android CI / package (push) Successful in 3m38sQRun-IO/ci-policy: Shared Android CI / package (push) Successful in 3m45sShared Android CI / gate (push) Successful in 16sQRun Android lifecycle / release (push) Successful in 1h10m27sQRun-IO/ci-policy: Shared Android CI / gate (push) Successful in 14sQRun-IO/ci-policy: ci / android-0 (push) Successful in 55m37sQRun-IO/ci-policy: ci / ci-result (push) Successful in 5sreleased this
2026-11-06 23:32:15 +00:00 | 19 commits to main since this releaseQQQ Mobile 1.0.2 (versionCode 4): Release notes
STATUS: PENDING CANDIDATE. Signed, not published, not a stable release, not yet device-requalified.
No scanner 1.0.2 tag, release or download exists. The only published release is the signed 1.0.0 preview (scanner-v1.0.0). This candidate supersedes the unpublished signed 1.0.1 (versionCode 3) candidate and updates it in place with the same signer. Central publication and final compatible server versions are not claimed.Install steps: INSTALL.md. Canonical docs:
INSTALLATION.md,
RELEASING.md,
ZEBRA-SCANNING.md.Artifact
Item Value Application ID io.qrun.mobile.scannerVersion 1.0.2 / versionCode 4 (replaces 1.0.1 / code 3 and 1.0.0 / code 2 in place) File QQQ-Mobile-1.0.2.apk, 15015419 bytesAPK SHA-256 8119492239F7D87264B3F48B0B6BF2E7F259942EED1978DEA1D2AB57A9B104F0Signer certificate SHA-256 BDDB2D2F45A5925C643A83ABAF616C1EAB2387DC5CDA7B645A6F4C0D5B17A9FFSigning Existing QRun release key, v2 + v3, one signer, non-debuggable, 16 KiB aligned. No new key. Release lint 0 errors, 0 warnings, 5 informational Source Built from mainateeb9f63322c11fddfd81f770e35808c7ff95ca32(treea807578b239ad790548957d3842b76b7d7007209): 1.0.1 source plus Android PR 17 and PR 18. Android PR 19 (release notes only) does not change the APK.The checksum proves file integrity only. Separately verify the signing certificate; only the same signer permits in-place updates.
What 1.0.2 changes
- Company sign-out completes: the provider logout request now runs before the scanner host ends its device session, so the browser end-session page opens. Previously the device-session end ran first and no
nativeLogoutDatacame back, so the browser never opened (observed on the MC9400 with the production APK against the real Authentik server). (PR 17) - OAuth user name: the signed-in user's name is shown after browser sign-in instead of a blank current user. (PR 17)
- Heartbeat versions: the app and OS version are reported on every session heartbeat, so scan receipts show the new version after an in-place update. Effective with mobile-scanners server 1.6.0; older servers ignore the keys. (PR 18)
Supported behavior (from 1.0.0 and 1.0.1)
Runtime customer branding from one shared APK; server-advertised sign-in; administrator device approval; portrait default orientation; Zebra EMDK capture forwarding the raw barcode, symbology and AIM identifier; record browsing and photo attachment through server record actions (camera or gallery) with preview, parent scoping and cleanup on logout.
Qualification status of this build
1.0.2 has not been installed on or requalified against any device. Nothing below was rerun with this APK. The three 1.0.2 changes were verified by hosted unit and end-to-end tests at merge only.
Historical evidence (1.0.1, versionCode 3; not rerun for 1.0.2)
Zebra MC9400 (production-signed 1.0.1):
- In-place update 1.0.0 → 1.0.1 preserved login and enrollment; enrollment over trusted HTTPS passed.
- Physical CODE128 scan saved and verified by the backend (symbology, AIM identifier, raw bytes, user, device).
- Gallery photo upload returned AVAILABLE with exact parent, type, size and hash.
Zebra TC22 (disposable native test build; its development-signed install and manual Echo acceptance were preserved):
- Camera/gallery photo upload AVAILABLE, thumbnail and full preview, parent scoping, rotation and logout cleanup passed.
Server/API: 185 requests across 23 operations matched the semantic API contract; UI API 1.10 discovery with strict nonce passed.
Limits: TC22 photo tests used a disposable build, and synthetic camera input is not camera-hardware acceptance.
Open gates (not claimed)
- Device requalification of 1.0.2: in-place update 1.0.1 → 1.0.2 (or 1.0.0 → 1.0.2) on the MC9400, scan, photo, and the company sign-out fix with the production APK.
- Native browser sign-in (Authentik) login, logout and account switching with the production APK.
- Public server cohort: the full downstream cohort (Core RC22 canonical Gitea files and hashes were independently verified) is still pending; final compatible public versions are not stated.
- GS1 physical print and rescan.
- Print nonce fix (merged
abc3d0d, 532 hosted tests passed): released in print client 1.2.1; not part of this scanner APK. - Publication: no 1.0.2 tag, release, hosted APK or download URL exists.
Compatibility
- Same signer and non-decreasing versionCode: in-place update. Development-signed installs need the explicit migration in INSTALL.md (resets settings, login and enrollment).
- Release builds reject HTTP; use trusted HTTPS only.
- Server needs the semantic UI API (core 1.8+; OAuth2 sign-in needs 1.10) and
mobile-scanners1.1+ (1.6.0+ to record heartbeat versions). Compatibility is checked before credentials are sent. - Online only; no offline queue.
Downloads
- Company sign-out completes: the provider logout request now runs before the scanner host ends its device session, so the browser end-session page opens. Previously the device-session end ran first and no
-
QQQ Mobile 1.0.0 — signed preview
Pre-ReleaseQRun-IO/ci-policy: ci / fork-guard (push) SkippedQRun-IO/ci-policy: ci / head-profile (push) SkippedQRun-IO/ci-policy: ci / application-template-0 (push) SkippedQRun-IO/ci-policy: ci / gradle-1 (push) SkippedQRun-IO/ci-policy: ci / java-docker-3 (push) SkippedQRun-IO/ci-policy: ci / java-docker-4 (push) SkippedQRun-IO/ci-policy: ci / java-frontend-browser-5 (push) SkippedQRun-IO/ci-policy: ci / java-maven-6 (push) SkippedQRun-IO/ci-policy: ci / java-maven-7 (push) SkippedQRun-IO/ci-policy: ci / node-8 (push) SkippedQRun-IO/ci-policy: ci / node-10 (push) SkippedQRun-IO/ci-policy: ci / node-9 (push) SkippedQRun-IO/ci-policy: ci / node-playwright-11 (push) SkippedQRun-IO/ci-policy: ci / repository-policy-12 (push) SkippedQRun-IO/ci-policy: ci / source-config-13 (push) SkippedQRun-IO/ci-policy: ci / source-config-14 (push) SkippedQRun-IO/ci-policy: ci / original-business (push) SkippedQRun-IO/ci-policy: ci / original-mcp (push) SkippedQRun-IO/ci-policy: ci / original-voyage (push) SkippedQRun-IO/ci-policy: ci / original-cli (push) SkippedQRun-IO/ci-policy: ci / not-enrolled (push) SkippedQRun-IO/ci-policy: native / fork-deny (push) SkippedQRun-IO/ci-policy: native / dotnet-0 (push) SkippedQRun-IO/ci-policy: native / native-result (push) Successful in 5sShared Android CI / unit-test (push) Successful in 4m2sShared Android CI / android-test (push) Successful in 9m49sShared Android CI / secrets (push) Successful in 17sQRun-IO/ci-policy: Shared Android CI / unit-test (push) Successful in 4m2sQRun-IO/ci-policy: ci / repository-policy (push) SkippedQRun-IO/ci-policy: ci / java-core-2-head (push) SkippedQRun-IO/ci-policy: ci / java-docker-3-head (push) SkippedQRun-IO/ci-policy: ci / java-maven-6-head (push) SkippedQRun-IO/ci-policy: ci / java-maven-7-head (push) SkippedQRun-IO/ci-policy: Shared Android CI / android-test (push) Successful in 9m46sQRun-IO/ci-policy: Shared Android CI / secrets (push) Successful in 17sShared Android CI / package (push) Successful in 3m35sQRun-IO/ci-policy: Shared Android CI / package (push) Successful in 3m28sShared Android CI / gate (push) Successful in 11sQRun Android lifecycle / release (push) Successful in 35m27sQRun-IO/ci-policy: Shared Android CI / gate (push) Successful in 12sQRun-IO/ci-policy: ci / android-0 (push) Successful in 21m30sQRun-IO/ci-policy: ci / ci-result (push) Successful in 3sreleased this
2026-11-04 23:50:45 +00:00 | 30 commits to main since this releaseQQQ Mobile for Android: signed preview for direct installation or MDM. Application ID: io.qrun.mobile.scanner. Version 1.0.0, versionCode 2.
This uses the permanent QRun-owned signing key. The APK is non-debuggable, requires HTTPS, and has verified v2/v3 signatures and 16 KiB alignment. Customer branding is supplied by the QQQ server; the shared launcher remains QQQ Mobile.
APK SHA-256: EE5AC896B8985AF6F11B2E883955925D6571A2913D74A4AACCDB564B79394D51
Signing certificate SHA-256: BDDB2D2F45A5925C643A83ABAF616C1EAB2387DC5CDA7B645A6F4C0D5B17A9FFApp source matches 0ae2101f082c241ca6a70462dc9ec3057aa6c906; the tagged
3eef6431commit adds documentation only. Release lint/build and signature verification passed. The signed APK was installed and launched on an MC9400 and its bytes read back exactly. TC22 workflow acceptance applies to the development-signed build of the same app source.Preview limitations: production-signed HTTPS enrollment, physical scanning and in-place update qualification remain pending. The online-only client needs a compatible QQQ 4.1 server with the Mobile Scanners QBit. Production builds cannot connect to a plain-HTTP local demo. Do not uninstall an existing demo app implicitly: its different signing key requires a planned migration and re-enrollment.
Download the APK and SHA256SUMS, verify both the checksum and signing certificate, then install through your approved device-management method. All future updates must retain this signing key and increase versionCode. No signing secrets are included.
Downloads