3.2 KiB
QR Scanner
Full-screen camera-based QR scanner. Returns the decoded string to the caller via activity result.
Activity — QrScannerActivity
File: ui/home/QrScannerActivity.kt. Hosts a CameraX preview + analysis pipeline backed by de.markusfisch.android.zxingcpp.ZxingCpp.
Reader Options
ZxingCpp.ReaderOptions(
tryHarder = true,
tryRotate = true,
tryInvert = true,
tryDownscale = true,
maxNumberOfSymbols = 1,
textMode = ZxingCpp.TextMode.PLAIN,
)
Camera Pipeline
startCamera() (QrScannerActivity.kt:186-240):
ProcessCameraProvider.getInstance()- Builds
PreviewandImageAnalysiswithHIGHEST_AVAILABLE_STRATEGY+RATIO_16_9_FALLBACK_AUTO_STRATEGY - Analyser receives
STRATEGY_KEEP_ONLY_LATESTframes; reads the Y-plane viaZxingCpp.readYBuffer(...)with the image rotation applied - On first hit,
deliverResult(text)setsActivity.RESULT_OKwithEXTRA_QR_CONTENTand finishes
Lock Guard
onCreate (QrScannerActivity.kt:101-106) checks CredentialStore.loadSecurityHash() and app.isUnlocked; if a lock exists and the app is locked, it forwards to LockActivity and finishes — direct intent launches cannot bypass the lock screen.
UI Controls
| Control | Behaviour |
|---|---|
Flashlight (btnFlashlight) |
Toggles camera.cameraControl.enableTorch(); icon swaps between ic_flashlight_to_on / ic_flashlight_to_off with an Animatable transition |
Zoom slider (zoomSlider) |
Linear zoom via setLinearZoom(); updated live from the camera's zoomState observer |
| Pinch-to-zoom | ScaleGestureDetector on the preview view, mapped through cameraControl.setZoomRatio() clamped to the device's [minZoomRatio, maxZoomRatio] |
Pick image (btnPickImage) |
GetContent("image/*"); decodes the picked bitmap with the same reader options |
Image Decoder Fallback
Bitmap.decodeQr() (QrScannerActivity.kt:243-249) mirrors BinaryEye: tries Binarizer.LOCAL_AVERAGE first, then falls back to GLOBAL_HISTOGRAM for tricky lighting.
Callers
Each caller registers an ActivityResultContracts.StartActivityForResult launcher and reads EXTRA_QR_CONTENT from the result intent.
| Caller | Result handling |
|---|---|
| TransferFragment | Routes PayMV / BML URL via PaymvQrParser + extractBmlGatewayUrl |
| PayMvQrFragment | Generation only — does not call the scanner directly |
CredentialsFragment (login) |
OtpauthParser.parse(raw) → fills etOtpSeed or shows a chooser for multi-entry QRs |
| DashboardFragment | BML URL → BML QR pay; PayMV → pre-fill Transfer; otherwise toast |
| CardsFragment | Same routing as Dashboard, scoped to the active BML card |
Share-to-Scan Fast Path
When another app shares an image directly to the activity-alias .ScanToPayActivity, MainActivity decodes the QR from the image before routing (it holds the URI permission only at that point). The decoded string is then forwarded as the share_qr_text extra. This bypasses the camera entirely.
← Notifications Next → Circular Nav