Skip to content

refactor(android): drop HMS Scan Kit backend, keep pure ML Kit QR scanning - #3

Merged
Chloemlla merged 1 commit into
mainfrom
chore/pure-mlkit-qr
Aug 12, 2026
Merged

refactor(android): drop HMS Scan Kit backend, keep pure ML Kit QR scanning#3
Chloemlla merged 1 commit into
mainfrom
chore/pure-mlkit-qr

Conversation

@Chloemlla

@Chloemlla Chloemlla commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Summary

Remove the Huawei HMS Scan Kit backend from the dual-backend QR scanner, keeping pure Google ML Kit + CameraX:

  • QrScannerView: delete QrScanBackend enum, HmsRemoteQrScanner, HmsScanAvailability, DualBackendQrScanner, findActivity. PermissionAwareQrScanner now delegates straight to the existing CameraX + ML Kit scanner
  • Gradle: drop com.huawei.hms:scanplus; keep com.google.mlkit:barcode-scanning:17.3.0 + CameraX 1.4.2
  • Remove Huawei Maven repo + HMS R8 keep/dontwarn rules (ML Kit/CameraX guardrails stay)
  • Delete QrScanBackendTest (only locked the removed scaffolding)

The Compose entry point contract (onQrCode callback) is unchanged; SynapseMobileApp requires no edits.

Why

Single, deterministic backend. ML Kit bundles its own native engine; the HMS RemoteView path depended on runtime HMS availability and only served as a rarely-hit preference.

Test plan

  • Static verification: zero residual huawei|scanplus|HmsScan|hmsscankit|Scan Kit|QrScanBackend references in tracked code
  • CI: unit tests (gradle testProductionDebugUnitTest) on this PR
  • CI: lint + release APK build on this PR
  • Manual: camera scan on a device

Summary by CodeRabbit

  • 功能改进

    • 条码扫描统一使用 CameraX 与 ML Kit,移除 Huawei Scan Kit 扫描路径及相关切换逻辑。
    • 扫描流程得到简化,授权相机后即可直接进行条码识别。
  • 维护

    • 清理 Huawei 扫描服务相关配置、构建规则和测试内容。

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b11bfeb7-ff7e-42db-aeaf-061e4bd2342a

📥 Commits

Reviewing files that changed from the base of the PR and between c9f45ae and 1c48103.

📒 Files selected for processing (5)
  • android/app/build.gradle.kts
  • android/app/proguard-rules.pro
  • android/app/src/main/java/com/chloemlla/synapse/mobile/ui/QrScannerView.kt
  • android/app/src/test/java/com/chloemlla/synapse/mobile/ui/QrScanBackendTest.kt
  • android/settings.gradle.kts
 ______________________________________________________________________________________________________________________________________________________________________
< Refactor early, refactor often. Just as you might weed and rearrange a garden, rewrite, rework, and re-architect code when it needs it. Fix the root of the problem. >
 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/pure-mlkit-qr

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…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.
@Chloemlla
Chloemlla merged commit ac8da0a into main Aug 12, 2026
2 of 3 checks passed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between c9f45ae and 1c48103.

📒 Files selected for processing (5)
  • android/app/build.gradle.kts
  • android/app/proguard-rules.pro
  • android/app/src/main/java/com/chloemlla/synapse/mobile/ui/QrScannerView.kt
  • android/app/src/test/java/com/chloemlla/synapse/mobile/ui/QrScanBackendTest.kt
  • android/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

Comment on lines +181 to 182
// ML Kit on-device barcode scanning (CameraX frames + album decode).
implementation("com.google.mlkit:barcode-scanning:17.3.0")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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。

Comment on lines +70 to 73
MlKitCameraQrScanner(
modifier = modifier,
preferredBackend = preferredBackend,
onQrCode = onQrCode,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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 || true

Repository: 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.kt

Repository: 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:


MlKitCameraQrScanner 销毁时完整停止 CameraX 和 ML Kit。

组件移除时,DisposableEffect 只关闭 analyzerExecutorcameraProviderFuture 的 listener 仍可能在销毁后绑定 PreviewImageAnalysis。请使用 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant