refactor(android): drop HMS Scan Kit backend, keep pure ML Kit QR scanning - #3
Conversation
|
Note Currently processing new changes in this PR. This may take a few minutes, please wait... ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…nning Remove the Huawei HMS Scan Kit path from the dual-backend scanner. QrScannerView now goes straight to the CameraX + ML Kit barcode scanner; the scanplus dependency, Huawei Maven repo, and HMS R8 rules are deleted. QrScanBackendTest, which only locked the removed dual-backend scaffolding, is removed. The Compose entry point contract (onQrCode callback) is unchanged.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@android/app/build.gradle.kts`:
- Around line 181-182: 在合并前完成发布验证:运行 CI 单元测试和 lint,构建 release
APK,并使用真实设备验证权限授予、CameraX/ML Kit 扫描、关闭后再次打开扫描器,以及 QrScannerView.kt 的 onQrCode
回调仍正确到达 SynapseMobileApp.kt。
In `@android/app/src/main/java/com/chloemlla/synapse/mobile/ui/QrScannerView.kt`:
- Around line 70-73: 确保 MlKitCameraQrScanner 的扫描配置仅接受 QR 条码:使用
BarcodeScannerOptions 将格式限制为 Barcode.FORMAT_QR_CODE,或在触发 onQrCode 前校验
barcode.format;同时避免在 SynapseMobileApp.kt 中重复实现同一校验。
- Around line 70-73: Update MlKitCameraQrScanner’s DisposableEffect cleanup to
mark the component disposed, prevent cameraProviderFuture’s listener from
binding Preview or ImageAnalysis after disposal, then clear the analyzer, unbind
all CameraX use cases, close BarcodeScanner, and finally shut down
analyzerExecutor.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: b11bfeb7-ff7e-42db-aeaf-061e4bd2342a
📒 Files selected for processing (5)
android/app/build.gradle.ktsandroid/app/proguard-rules.proandroid/app/src/main/java/com/chloemlla/synapse/mobile/ui/QrScannerView.ktandroid/app/src/test/java/com/chloemlla/synapse/mobile/ui/QrScanBackendTest.ktandroid/settings.gradle.kts
💤 Files with no reviewable changes (3)
- android/settings.gradle.kts
- android/app/src/test/java/com/chloemlla/synapse/mobile/ui/QrScanBackendTest.kt
- android/app/proguard-rules.pro
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Build signed release APK
- GitHub Check: Build signed release APK
🔇 Additional comments (1)
android/app/src/main/java/com/chloemlla/synapse/mobile/ui/QrScannerView.kt (1)
4-4: LGTM!Also applies to: 50-55, 109-110
| // ML Kit on-device barcode scanning (CameraX frames + album decode). | ||
| implementation("com.google.mlkit:barcode-scanning:17.3.0") |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔵 Trivial
在合并前完成发布包和真机扫描验证。
删除 scanplus 后,扫描器只依赖 CameraX 1.4.2 和 ML Kit 17.3.0。请完成 CI 单元测试、lint、release APK 构建,并在真实设备上验证权限授予、扫描、关闭扫描器后再次打开,以及 onQrCode 回调仍到达 SynapseMobileApp.kt。
依据 PR objectives 和 QrScannerView.kt 的 CameraX/ML Kit 使用。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@android/app/build.gradle.kts` around lines 181 - 182, 在合并前完成发布验证:运行 CI 单元测试和
lint,构建 release APK,并使用真实设备验证权限授予、CameraX/ML Kit 扫描、关闭后再次打开扫描器,以及
QrScannerView.kt 的 onQrCode 回调仍正确到达 SynapseMobileApp.kt。
| MlKitCameraQrScanner( | ||
| modifier = modifier, | ||
| preferredBackend = preferredBackend, | ||
| onQrCode = onQrCode, | ||
| ) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win
确认 onQrCode 只接收 QR 条码。
此入口现在直接使用 MlKitCameraQrScanner。实现调用 BarcodeScanning.getClient(),不传入 BarcodeScannerOptions,随后只读取 barcode.rawValue,不检查 barcode.format。如果 ML Kit 17.3.0 的默认客户端返回多种条码,非 QR 条码也会传给 onQrCode。
如果登录流程要求 QR-only,请使用 BarcodeScannerOptions 设置 Barcode.FORMAT_QR_CODE,或在回调前检查 barcode.format。同时确认 SynapseMobileApp.kt 的下游逻辑没有依赖重复校验。
依据本文件的 ML Kit 创建逻辑和 onQrCode 回调契约。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@android/app/src/main/java/com/chloemlla/synapse/mobile/ui/QrScannerView.kt`
around lines 70 - 73, 确保 MlKitCameraQrScanner 的扫描配置仅接受 QR 条码:使用
BarcodeScannerOptions 将格式限制为 Barcode.FORMAT_QR_CODE,或在触发 onQrCode 前校验
barcode.format;同时避免在 SynapseMobileApp.kt 中重复实现同一校验。
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- candidate files ---'
fd -i 'QrScannerView|SynapseMobileApp' . || true
printf '%s\n' '--- relevant symbols and APIs ---'
rg -n -C 8 \
'MlKitCameraQrScanner|DisposableEffect|bindToLifecycle|ProcessCameraProvider|cameraProviderFuture|BarcodeScanning|getClient|analyzerExecutor|ImageAnalysis|Preview|BarcodeScanner|showScanner' \
android/app/src/main/java 2>/dev/null || trueRepository: Chloemlla/Synapse-Client
Length of output: 50380
🏁 Script executed:
#!/bin/bash
set -eu
printf '%s\n' '--- QrScannerView.kt implementation ---'
sed -n '109,195p' android/app/src/main/java/com/chloemlla/synapse/mobile/ui/QrScannerView.kt
printf '%s\n' '--- dependency declarations ---'
rg -n -C 3 \
'camera-(core|lifecycle|view)|cameraX|mlkit|barcode-scanning|play-services-mlkit' \
android --glob '*.gradle' --glob '*.gradle.kts' --glob 'libs.versions.toml' --glob 'gradle.properties' || true
printf '%s\n' '--- scanner lifecycle call sites ---'
rg -n -C 4 \
'PermissionAwareQrScanner\(|MlKitCameraQrScanner\(|acceptScannedPayload|setScannerVisible' \
android/app/src/main/java/com/chloemlla/synapse/mobile/ui/QrScannerView.kt \
android/app/src/main/java/com/chloemlla/synapse/mobile/ui/SynapseMobileApp.kt \
android/app/src/main/java/com/chloemlla/synapse/mobile/ui/SynapseLoginViewModel.ktRepository: Chloemlla/Synapse-Client
Length of output: 12209
🌐 Web query:
Official Android documentation for CameraX ProcessCameraProvider.unbindAll(), ImageAnalysis.clearAnalyzer(), ML Kit BarcodeScanner close(), and Task addOnCompleteListener cancellation/lifecycle behavior
💡 Result:
The following summarizes the documentation and behavior for the requested Android components: ProcessCameraProvider.unbindAll: This method unbinds all UseCases previously bound to a LifecycleOwner and removes them from CameraX [1][2]. It initiates a close of every currently open camera and is required to be called on the main thread [1][2]. When rebinding new UseCases, unbinding is typically implicit, so calling unbindAll is generally only necessary when you want to explicitly disconnect all camera operations from the lifecycle [1][3]. ImageAnalysis.clearAnalyzer: This method removes a previously set analyzer from the ImageAnalysis use case [4][5]. Once called, data will stop streaming to the analyzer [4][5]. It is commonly used to stop analysis when the component is no longer needed or before setting a new analyzer [6]. ML Kit BarcodeScanner.close: The BarcodeScanner should be explicitly closed using the close method when it is no longer needed to release underlying resources [7][8]. Failure to do so may lead to memory leaks or resource exhaustion. Task.addOnCompleteListener Lifecycle/Cancellation: - Behavior: A Task is considered complete if it succeeds, fails, or is canceled [9][10]. The OnCompleteListener is scheduled to run on the main thread when this completion occurs [11][9]. - Lifecycle Management: To prevent callbacks from executing after an Activity or Fragment has been destroyed (which could cause exceptions if accessing closed resources), you should use Activity-scoped listeners [12][13]. Passing an Activity as the first argument to addOnCompleteListener(activity, listener) automatically removes the listener during the activity's onStop lifecycle method [12][9][10]. - Cancellation: Cancellation is supported by some Task types (e.g., CancellableTask). If a task is canceled, its listeners (including those added via addOnCompleteListener) will be notified, and the task's isCanceled state will return true [14][15]. Note that Task callbacks may still trigger after destruction if they are not correctly scoped, making Activity-scoped listeners the recommended mitigation [13].
Citations:
- 1: https://developer.android.com/reference/kotlin/androidx/camera/lifecycle/ProcessCameraProvider
- 2: https://developer.android.com/reference/androidx/camera/lifecycle/ProcessCameraProvider
- 3: https://developer.android.com/media/camera/camerax/architecture
- 4: https://developer.android.com/reference/kotlin/androidx/camera/core/ImageAnalysis
- 5: https://developer.android.com/reference/androidx/camera/core/ImageAnalysis
- 6: https://developer.android.com/media/camera/camerax/analyze
- 7: https://developers.google.cn/android/reference/com/google/mlkit/vision/barcode/BarcodeScanning
- 8: https://developers.google.com/android/reference/com/google/mlkit/vision/barcode/BarcodeScanner
- 9: https://developers.google.com/android/reference/kotlin/com/google/android/gms/tasks/Task
- 10: https://developers.google.cn/android/reference/kotlin/com/google/android/gms/tasks/Task
- 11: https://developer.android.google.cn/reference/com/google/android/play/core/tasks/Task
- 12: https://developers.google.com/android/guides/tasks
- 13: https://developers.google.cn/ml-kit/known-issues
- 14: https://firebase.google.com/docs/reference/android/com/google/firebase/storage/CancellableTask
- 15: https://firebase.google.cn/docs/reference/android/com/google/firebase/storage/StorageTask
在 MlKitCameraQrScanner 销毁时完整停止 CameraX 和 ML Kit。
组件移除时,DisposableEffect 只关闭 analyzerExecutor。cameraProviderFuture 的 listener 仍可能在销毁后绑定 Preview 和 ImageAnalysis。请使用 disposed 标志阻止该绑定,并在销毁时清理分析器、解绑用例、调用 BarcodeScanner.close(),最后关闭 executor。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@android/app/src/main/java/com/chloemlla/synapse/mobile/ui/QrScannerView.kt`
around lines 70 - 73, Update MlKitCameraQrScanner’s DisposableEffect cleanup to
mark the component disposed, prevent cameraProviderFuture’s listener from
binding Preview or ImageAnalysis after disposal, then clear the analyzer, unbind
all CameraX use cases, close BarcodeScanner, and finally shut down
analyzerExecutor.
Summary
Remove the Huawei HMS Scan Kit backend from the dual-backend QR scanner, keeping pure Google ML Kit + CameraX:
QrScannerView: deleteQrScanBackendenum,HmsRemoteQrScanner,HmsScanAvailability,DualBackendQrScanner,findActivity.PermissionAwareQrScannernow delegates straight to the existing CameraX + ML Kit scannercom.huawei.hms:scanplus; keepcom.google.mlkit:barcode-scanning:17.3.0+ CameraX1.4.2QrScanBackendTest(only locked the removed scaffolding)The Compose entry point contract (
onQrCodecallback) is unchanged;SynapseMobileApprequires no edits.Why
Single, deterministic backend. ML Kit bundles its own native engine; the HMS
RemoteViewpath depended on runtime HMS availability and only served as a rarely-hit preference.Test plan
huawei|scanplus|HmsScan|hmsscankit|Scan Kit|QrScanBackendreferences in tracked codegradle testProductionDebugUnitTest) on this PRSummary by CodeRabbit
功能改进
维护