react-native-document-scanner:基于 React Native 鸿蒙生态的文档扫描组件项目

实时文档扫描与裁剪

Branch3Tags2
FilesLast commitLast update
14 days ago
14 days ago
15 days ago
1 month ago
1 month ago
1 month ago
1 month ago
1 month ago
24 days ago
15 days ago
14 days ago
14 days ago
1 month ago
14 days ago
1 month ago

@hxa-rn/react-native-document-scanner

本项目基于 react-native-document-scanner 开发。如果在使用过程中有任何问题,欢迎在 GitCode 提交 Issue,会及时跟进。

项目介绍

@hxa-rn/react-native-document-scanner 是 react-native-document-scanner(上游版本 1.4.2)的鸿蒙(OpenHarmony / HarmonyOS,RNOH)适配包,当前版本 1.4.2(与上游版本号一致)。

上游是一个文档扫描库:拍摄纸质文档、自动识别边框并做透视裁剪,把裁剪后的图片以文件路径或 Base64 字符串的形式回传给业务方,并在取景过程中回报每次边框检测的结果。

鸿蒙适配版提供两种扫描引擎,二者都在全屏扫描会话中运行:

  • Vision Kit 引擎(缺省):基于系统文档扫描控件(@hms.ai.DocumentScanner),控件内完成取景、自动拍摄、裁剪、滤镜、编辑与保存;
  • 自建取景引擎:基于 Camera Kit 相机会话与 ArkUI XComponent 预览,实现上游的实时边框检测(onRectangleDetect)、检测框遮罩(overlayColor)、手电筒(enableTorch)、前后摄切换(useFrontCam)、自动拍摄阈值与检测间隔,并回传真实的裁剪前原图与四角坐标。

两种引擎都支持:单张与连续拍摄、文件路径或 Base64 回传、逐张触发 onPictureTaken、quality / brightness / saturation / contrast 对结果图生效、结构化错误码。

⚠️ 交互模型与上游不同(重要):上游是内嵌在 RN 视图树里的实时相机取景组件;鸿蒙侧两种引擎的取景都在独立的全屏会话中进行,不内嵌在 RN 页面内。<DocumentScanner> 在页面上渲染一个触发面,点击它或调用 ref.startScan() 拉起全屏扫描会话,扫描结束后回到原页面。

鸿蒙适配包版本 上游版本 React Native / RNOH 编译 SDK 接入方式
1.4.2 1.4.2 RN >=0.72(基于 0.72.5 + @react-native-oh/react-native-harmony 0.72.143) compatibleSdkVersion 5.1.0(18),targetSdkVersion 6.1.1(24) Autolink(RNOH hvigor 插件)或 Manual Link,两条路线均须通过 tgz / npm 公仓安装验收

包内鸿蒙模块的 ohpm 名为 @oh-rn/react-native-document-scanner(源码 HAR harmony/document_scanner.har,同源源码目录 harmony/document_scanner),与 npm 包名不同;下文接入步骤里两个名字请照抄,不要互换。

集成指南

1. 安装

npm install @hxa-rn/react-native-document-scanner@1.4.3 --legacy-peer-deps

命令带 --legacy-peer-deps,用于避免 RN 0.72 宿主安装时的 peer 冲突。peerDependencies:react-native >= 0.72,react *。

2. JS 侧导入

包内已声明 harmony.alias 为 react-native-document-scanner。宿主 Metro 配置使用 RNOH 的 createHarmonyMetroConfig(RNOH 工程模板默认如此)时,打包会把上游包名重定向到本包,业务代码仍从上游包名导入:

import DocumentScanner, { RNPdfScannerManager } from 'react-native-document-scanner';

3. 鸿蒙原生接入

包内 harmony/document_scanner.har 是源码 HAR(含 ETS 源码、C++ 源码与 codegen 产物,ohpm 名 @oh-rn/react-native-document-scanner)。接入分两条路线,二选一,不要同时做(否则 CMake 会报同一 binary dir 被用两次)。本仓 example、example_auto 两个示例宿主走路线 B(Manual Link),可对照参考。

① 工程根 oh-package.json5:为 RNOH 框架配置 overrides,指向宿主正在使用的 RNOH HAR。下例为 RNOH 官方预编译包,与本仓示例相同:

{
  "overrides": {
    "@rnoh/react-native-openharmony": "file:../node_modules/@react-native-oh/react-native-harmony/react_native_openharmony_release.har"
  }
}

本模块自身对 @rnoh/react-native-openharmony 的依赖写的是相对路径 file:../react_native_openharmony_release.har,必须依靠上面这条 overrides 指到宿主的 RNOH,否则 ohpm install 会报找不到该 HAR。

② entry/oh-package.json5:依赖包内的 HAR:

"dependencies": {
  "@oh-rn/react-native-document-scanner": "file:../../node_modules/@hxa-rn/react-native-document-scanner/harmony/document_scanner.har"
}

在 harmony 工程目录执行 ohpm install --all(或在 DevEco Studio 中 Sync)。ohpm 会把 HAR 解包成工程内 oh_modules/@oh-rn/react-native-document-scanner/ 目录(含 src/main/cpp),后续 CMake 与 ETS 导入都从这里解析。

路线 A:Autolink(宿主 hvigorfile.ts 使用 RNOH 的 createRNOHModulePlugin 且开启 autolinking)

package.json 已声明 harmony.autolinking(cmakeLibraryTargetName document_scanner、ohPackageName @oh-rn/react-native-document-scanner、etsPackageClassName / cppPackageClassName DocumentScannerPackage)。构建时插件会自动:把 ② 的依赖写入工程根 oh-package.json5、生成 entry/src/main/cpp/autolinking.cmake 与 RNOHPackagesFactory.h / RNOHPackagesFactory.ets 并注册 DocumentScannerPackage。宿主只需保证 CMakeLists.txt 里有 include("${CMAKE_CURRENT_SOURCE_DIR}/autolinking.cmake") 与 autolink_libraries(rnoh_app)、PackageProvider.cpp / RNPackagesFactory.ets 里合并了 createRNOHPackages(ctx)(RNOH 工程模板默认如此),不要再手动注册。

路线 B:Manual Link(宿主未启用 autolinking,或在 hvigorfile.ts 的 autolinking.excludeNpmPackages 中写入了 '@hxa-rn/react-native-document-scanner')

排除项按 npm 包名匹配,写成 ohpm 名 @oh-rn/… 不会生效。

③ entry/src/main/cpp/CMakeLists.txt:

# RNOH 模板工程已定义 OH_MODULE_DIR;未定义时先加:
# set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
add_subdirectory("${OH_MODULE_DIR}/@oh-rn/react-native-document-scanner/src/main/cpp" ./document_scanner)

target_link_libraries(rnoh_app PUBLIC document_scanner)

④ entry/src/main/cpp/PackageProvider.cpp:

#include "RNOH/PackageProvider.h"
#include "DocumentScannerPackage.h"

using namespace rnoh;

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    return {
        std::make_shared<DocumentScannerPackage>(ctx),
    };
}

⑤ entry/src/main/ets/RNPackagesFactory.ets:

import { RNPackageContext, RNPackage } from '@rnoh/react-native-openharmony/ts';
import DocumentScannerPackage from '@oh-rn/react-native-document-scanner';

export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [
    new DocumentScannerPackage(ctx),
  ];
}

包内同时附带源码目录 harmony/document_scanner/(与 HAR 同源),供查阅或自行 assembleHar;不要把它以 file: 源码目录方式直接作为 ohpm 依赖——ohpm 会以 junction 链接到工程外,hvigor 的 CompileArkTS 会报 EINVAL: invalid argument, mkdir '…\C:'。

4. 宿主工程还需接线三处

鸿蒙的 HAR 模块不能自行声明 Ability、页面与权限。两种引擎各需要一个承载 Ability 与一个承载页,以下三处必须由宿主应用完成;缺任一项,对应引擎的 startScan() 会以错误码 reject。所需文件已随包附在 host-template/(与示例宿主逐字一致),复制即可。

1. 声明相机权限(entry/src/main/module.json5),usedScene.abilities 必须同时列出两个承载 Ability:

"requestPermissions": [
  {
    "name": "ohos.permission.CAMERA",
    "reason": "$string:camera_reason",
    "usedScene": { "abilities": ["DocumentScannerAbility", "SelfBuiltScannerAbility"], "when": "inuse" }
  }
]

$string:camera_reason 需在宿主 resources/base/element/string.json 中定义。

2. 声明两个承载 Ability(entry/src/main/module.json5 的 abilities):

{
  "name": "DocumentScannerAbility",
  "srcEntry": "./ets/documentscannerability/DocumentScannerAbility.ets",
  "description": "$string:EntryAbility_desc",
  "icon": "$media:layered_image",
  "label": "$string:EntryAbility_label",
  "startWindowIcon": "$media:startIcon",
  "startWindowBackground": "$color:start_window_background",
  "launchType": "singleton",
  "exported": false
},
{
  "name": "SelfBuiltScannerAbility",
  "srcEntry": "./ets/documentscannerability/SelfBuiltScannerAbility.ets",
  "description": "$string:EntryAbility_desc",
  "icon": "$media:layered_image",
  "label": "$string:EntryAbility_label",
  "startWindowIcon": "$media:startIcon",
  "startWindowBackground": "$color:start_window_background",
  "launchType": "singleton",
  "exported": false
}

description / icon / label / startWindowIcon / startWindowBackground 五项照抄宿主自己 EntryAbility 的取值即可。

两个 srcEntry 都是继承本库基类的空子类,直接复制包内 host-template/DocumentScannerAbility.ets 与 host-template/SelfBuiltScannerAbility.ets 到 entry/src/main/ets/documentscannerability/:

import { DocumentScannerAbility as BaseDocumentScannerAbility } from '@oh-rn/react-native-document-scanner';
export default class DocumentScannerAbility extends BaseDocumentScannerAbility {}
import { SelfBuiltScannerAbility as BaseSelfBuiltScannerAbility } from '@oh-rn/react-native-document-scanner';
export default class SelfBuiltScannerAbility extends BaseSelfBuiltScannerAbility {}

3. 提供两个承载页并注册进 main_pages.json:pages/DocumentScannerPage(挂载 Vision Kit 控件)与 pages/SelfBuiltScannerPage(相机预览、检测遮罩与控制条),两者都用本库导出的函数完成配置折算、结果回传与错误回传。复制包内 host-template/DocumentScannerPage.ets 与 host-template/SelfBuiltScannerPage.ets 到 entry/src/main/ets/pages/,并在 entry/src/main/resources/base/profile/main_pages.json 中加入:

{
  "src": [
    "pages/Index",
    "pages/DocumentScannerPage",
    "pages/SelfBuiltScannerPage"
  ]
}

只打算使用 Vision Kit 引擎时也请完成自建取景引擎的接线:调用方一旦传入 onRectangleDetect、enableTorch 等属性就会自动切换到自建取景引擎。

使用说明

基础用法

import React from 'react';
import { View, Image } from 'react-native';
import DocumentScanner from 'react-native-document-scanner';

export default function Demo() {
  const scannerRef = React.useRef(null);
  const [image, setImage] = React.useState(null);

  return (
    <View>
      <DocumentScanner
        ref={scannerRef}
        captureMultiple={false}
        useBase64={false}
        quality={0.8}
        onPictureTaken={(data) => setImage(data.croppedImage)}
      />
      {image ? <Image source={{ uri: image }} style={{ width: 200, height: 200 }} /> : null}
    </View>
  );
}

以上写法不涉及取景微调属性,使用 Vision Kit 引擎。需要实时检测回调或取景微调时,直接写出对应属性即可切换到自建取景引擎:

<DocumentScanner
  ref={scannerRef}
  overlayColor="rgba(255,130,0,0.7)"
  enableTorch={false}
  detectionCountBeforeCapture={5}
  detectionRefreshRateInMS={50}
  onRectangleDetect={({ stableCounter, lastDetectionType }) => console.log(stableCounter, lastDetectionType)}
  onPictureTaken={(data) => console.log(data.croppedImage, data.rectangleCoordinates)}
/>
  • scanEngine 未传(或为 'auto')时:写出 overlayColor、enableTorch、useFrontCam、detectionCountBeforeCapture、detectionRefreshRateInMS、onRectangleDetect 中任意一项(即使值为 false 或 undefined)即使用自建取景引擎,一项都不写则使用 Vision Kit 引擎;
  • 也可显式指定 scanEngine="visionkit" 或 scanEngine="selfbuilt";
  • onRectangleDetect 的参数直接就是 { stableCounter, lastDetectionType },写法与上游一致。

命令式拉起扫描

// 拉起全屏扫描会话;会话结束(保存、取消或失败)时返回
const result = await scannerRef.current.startScan();
// result = { cancelled: boolean, code: number, pictures: Picture[] }

capture() 按调用时的会话状态执行:

调用时机 ref.capture() / RNPdfScannerManager.capture() 的行为
没有进行中的扫描会话 ref.capture() 等同于 startScan()(使用组件当前属性);RNPdfScannerManager.capture() 以默认配置(单张、文件路径、Vision Kit 引擎)拉起会话,结果只在返回值中,不触发组件的 onPictureTaken
自建取景会话进行中 立即拍一张,返回 { cancelled: false, code: 200, pictures: [该张] };正在拍摄或会话已关闭时返回 { cancelled: true, code: -1, pictures: [] }。该张同时计入本次会话结果
Vision Kit 会话进行中 以 document_scanner_busy reject(系统控件不支持从外部触发拍摄)

扫描会话期间 RN 页面处于后台,JS 定时器暂停,事件回调照常到达。因此会话中的 capture() 请在 onRectangleDetect 等事件回调中调用,或直接点击自建取景界面上的「拍摄」按钮:

<DocumentScanner
  ref={scannerRef}
  scanEngine="selfbuilt"
  onRectangleDetect={({ stableCounter }) => {
    if (stableCounter === 2) {
      scannerRef.current.capture().then((shot) => console.log(shot.pictures.length));
    }
  }}
/>

上游的 NativeModules.RNPdfScannerManager.capture() 在鸿蒙侧改为具名导出:

import { RNPdfScannerManager } from 'react-native-document-scanner';

const result = await RNPdfScannerManager.capture();

连续拍摄与 Base64

<DocumentScanner
  captureMultiple          // 一次会话可连续拍摄多张
  maxShotCount={5}         // 单次会话最多 5 张(缺省 9)
  useBase64                // 结果以 Base64 字符串返回,而非文件路径
  onPictureTaken={(data) => console.log(data.croppedImage.length)}
/>

onPictureTaken 在扫描会话结束时按顺序逐张触发。

错误处理

try {
  await scannerRef.current.startScan();
} catch (e) {
  // e.code 为结构化错误码,e.message 为可读描述
  console.warn(e.code, e.message);
}

接口文档

组件属性

属性 类型 默认值 说明 鸿蒙支持
captureMultiple boolean false 是否连续拍摄 ✅ 两种引擎均生效。严格布尔判定:仅 true 视为开启,字符串 'true'、数字 1 等按 false 处理
maxShotCount number 9 captureMultiple 为 true 时单次会话最多拍摄的张数(鸿蒙新增) ✅ 两种引擎均生效。正整数向下取整,非法值按 9 处理
useBase64 boolean false 结果以 Base64 字符串返回,而非文件路径 ✅ 两种引擎均生效
scanButtonText string '点击扫描文档' 触发面按钮文案(鸿蒙新增) ✅ 生效
scanEngine 'visionkit' | 'selfbuilt' | 'auto' 'auto' 选择扫描引擎(鸿蒙新增),'auto' 规则见「使用说明」 ✅ 生效。非法值按 'auto' 处理
manualOnly boolean false 关闭自动拍摄,只允许手动拍(按上游 1.4.3 语义提供) ✅ 两种引擎均生效:Vision Kit 切手动拍摄模式;自建取景不再按 detectionCountBeforeCapture 自动拍
onPictureTaken (data) => void 空函数 每张图片触发一次,载荷见下表 ✅ 两种引擎均生效,在会话结束时逐张触发
onRectangleDetect ({ stableCounter, lastDetectionType }) => void — 每次检测到文档边框时触发 ✅ 自建取景引擎生效;Vision Kit 引擎下不触发
overlayColor string | number 不绘制 检测框遮罩颜色,支持 #RRGGBBAA、rgba() 等;数值按 0xAARRGGBB 解析 ✅ 自建取景引擎生效;Vision Kit 引擎下不生效
enableTorch boolean false 手电筒 ✅ 自建取景引擎生效(设备不支持时不动作);Vision Kit 引擎下不生效
useFrontCam boolean false 使用前置摄像头 ✅ 自建取景引擎生效(启动时设备没有所需摄像头会以 document_scanner_no_camera reject;在取景界面切换时没有对应摄像头则保持当前摄像头);Vision Kit 引擎下不生效
detectionCountBeforeCapture number 5 连续检出的合格边框数超过该值时自动拍摄(缺省第 6 次) ✅ 自建取景引擎生效;Vision Kit 引擎下不生效
detectionRefreshRateInMS number 50 两次边框检测的间隔,实际间隔为该值 × 10 毫秒(缺省约 0.5 秒,与上游一致) ✅ 自建取景引擎生效;Vision Kit 引擎下不生效
brightness number 0 结果图亮度 ✅ 两种引擎均对结果图调色;自建取景引擎只作用于裁剪成功的 croppedImage
saturation number 1 结果图饱和度(传 0 与上游一样按 1 处理) ✅ 同 brightness
contrast number 1 结果图对比度 ✅ 同 brightness
quality number 0.8 JPEG 压缩质量,取值钳制到 0.1~1 ✅ 两种引擎均生效:显式传入数值时按该质量重新编码结果图;未传时保留引擎原始图片

实例方法

方法 签名 说明
startScan() () => Promise<ScanResult> 拉起全屏扫描会话(鸿蒙新增)。会话结束时 resolve;拉起失败时 reject
capture() () => Promise<ScanResult> 对齐上游 capture():无会话时等同于 startScan();自建取景会话中立即拍一张;Vision Kit 会话中 reject document_scanner_busy
RNPdfScannerManager.capture() () => Promise<ScanResult> 具名导出,对应上游 NativeModules.RNPdfScannerManager.capture()。会话中的行为同 capture();无会话时以默认配置拉起会话,不触发组件回调

返回值与回调载荷

ScanResult:

字段 类型 说明
cancelled boolean 用户取消、未保存任何图片或会话失败时为 true
code number 200 表示成功;取消时为 -1
pictures Picture[] 逐张结果;cancelled 为 true 时为空数组

onPictureTaken 的载荷(即 Picture):

字段 类型 说明
croppedImage string 裁剪后的图片:file:// URI 或 Base64 字符串(不含换行),取决于 useBase64
initialImage string 裁剪前原图。Vision Kit 引擎下与 croppedImage 取值相同;自建取景引擎下为未裁剪的原始拍照图(未能裁剪时与 croppedImage 相同)
rectangleCoordinates object | null 四角坐标 { topLeft, topRight, bottomLeft, bottomRight },每个角为 { x, y }。Vision Kit 引擎下恒为 null;自建取景引擎裁剪成功时为拍照图像素坐标,未能裁剪时为 null

onRectangleDetect 的参数:

字段 类型 说明
stableCounter number 连续检出合格边框的次数;检出非合格边框时清零,未检出边框时保持不变
lastDetectionType number 本次检出的边框类型:0 合格、1 角度不佳、2 距离过远

错误码

startScan() / capture() / RNPdfScannerManager.capture() reject 时,error.code 为下列之一,error.message 为可读描述:

错误码 含义 常见原因
document_scanner_busy 已有扫描会话在进行中 上一次会话尚未结束时再次 startScan();或在 Vision Kit 会话中调用 capture()
document_scanner_permission_denied 相机权限被拒绝 用户在系统权限弹窗上选择了「不允许」,或宿主未声明相机权限(见「集成指南」第 4 节第 1 步)
document_scanner_no_context 无法拉起扫描会话 宿主未声明对应的承载 Ability(见「集成指南」第 4 节第 2 步)
document_scanner_permission_not_declared 相机权限申请异常 权限申请所用上下文不合法
document_scanner_load_content_failed 扫描页加载失败 宿主未提供承载页或未注册进 main_pages.json(见「集成指南」第 4 节第 3 步)
document_scanner_no_camera 没有可用的摄像头 自建取景引擎下设备无摄像头、要求前置摄像头但设备没有,或摄像头无可用预览规格
document_scanner_camera_session_failed 相机会话启动失败 自建取景引擎下系统相机会话装配或启动出错

其他底层异常会原样抛出(无 code 字段)。

快速验证(运行 Example)

前置条件

依赖 版本要求
Node.js >= 20(示例工程 engines 要求)
DevEco Studio 6.1.1(示例验证用 6.1.1.290)
HarmonyOS SDK API 18+(example/harmony 的 compatibleSdkVersion 为 5.1.0(18))
路径 Windows 下仓库根目录的完整路径不超过 40 个字符,否则原生构建的中间文件路径会超过系统上限

运行步骤

1. 克隆仓库

git clone -b br_rnoh0.72 https://gitcode.com/hxa-rn/react-native-document-scanner.git
cd react-native-document-scanner

Windows 下可在克隆时指定短目录名,例如 git clone -b br_rnoh0.72 https://gitcode.com/hxa-rn/react-native-document-scanner.git C:\rds。

2. 进入 example 目录,安装依赖

cd example
npm install --legacy-peer-deps

Example 从 npm 公仓安装 @hxa-rn/react-native-document-scanner@1.4.3,不需要在仓根执行 npm pack。

3. 生成 JS Bundle

npm run dev

产物:harmony/entry/src/main/resources/rawfile/bundle.harmony.js

4. 用 DevEco Studio 打开鸿蒙工程

  • 打开 DevEco Studio,选择 example/harmony 目录
  • 首次构建请在 File → Project Structure → Signing Configs 勾选 Automatically generate signature,Apply 后 Sync
  • 等待 Sync 完成

5. 编译并运行 HAP

在 DevEco Studio 中点击运行按钮,将 HAP 安装到设备。

example_auto(自动化用例工程)步骤相同,把 example 换成 example_auto 即可,两者的依赖与构建输出相互独立。

注意:Example 已预置 HAR 依赖、Package 注册(Manual Link)、两个 Ability 子类、两个扫描页面(均已登记进 main_pages.json)以及相机权限声明,无需手动配置。编 HAP 前必须先执行 npm run dev;改过 JS 后重新执行再运行。

约束与限制

兼容性

项 值
适配的鸿蒙 SDK compatibleSdkVersion 5.1.0(18)、targetSdkVersion 6.1.1(24),runtimeOS HarmonyOS
依赖的系统能力 Vision Kit 文档扫描控件 @hms.ai.DocumentScanner(@kit.VisionKit,起始版本 5.0.0(12));Camera Kit(@ohos.multimedia.camera);Image Kit、Effect Kit、Core File Kit(结果图处理)
上游库版本 react-native-document-scanner 1.4.2
React Native >=0.72(适配基于 0.72.5 + @react-native-oh/react-native-harmony 0.72.143)
支持设备类型 default(手机)、tablet(平板)、2in1;Vision Kit 文档扫描控件官方仅支持手机、平板

验证状态

  • 真机黑盒:适配源码此前的构建包已在 API 22 / 23 / 24 / 26 四档真机按 20 条用例完成黑盒验证,四档累计 80/80 通过,Vision Kit 与自建取景两条引擎路径均覆盖(整体测试报告日期 2026-09-16)。
  • API 24 定向复测(2026-09-25)对应基线 f479aa0 的历史构建包:修复手电筒状态回读与输出路径等问题;纸张检测与透视裁剪质量一项因机位缺受控场景记为部分通过。
  • 当前源码(f007b4e,含上述修复)只做过 release 重建与离线核验;该重建包与本 npm 包均未在真机安装运行。
  • 本 npm 包(1.4.2):代码与 1.0.0 相同,仅版本号改为与上游版本一致;发布前以候选 tgz 为依赖,两个示例在 DevEco Studio 6.1.1.290、RNOH 0.72.143(官方预编译包)下完成 release assembleHap;未在真机安装运行。
  • npm 包 1.0.0:2026-09-28 发布时,两个示例先只通过候选 tgz 安装本包、发布后再从 npmjs 精确安装 1.0.0,均完成 release assembleHap(DevEco Studio 6.1.1.290、RNOH 0.72.143,当时示例以源码模式编译 RNOH)。示例此后改用 RNOH 官方预编译包,已在 Windows 上编译通过。
  • 只在上述环境验证过;不据此声明所有 RNOH 版本或所有 API 版本均兼容。

权限

本库依赖 1 项系统权限:

权限 类型 用途
ohos.permission.CAMERA user_grant 两种引擎扫描时的相机取景与拍摄

⚠️ 该权限为 user_grant,且 HAR 模块不能自行声明权限:

  • 宿主应用必须在自己的 entry/src/main/module.json5 中声明它,并在 usedScene.abilities 中同时列出 DocumentScannerAbility 与 SelfBuiltScannerAbility(见「集成指南」第 4 节第 1 步);
  • 运行时的动态申请由本库在承载 Ability 内自动完成,宿主无需重复申请;
  • 用户拒绝授权时,startScan() 会以 document_scanner_permission_denied reject。

使用约束

  • 交互模型:两种引擎的扫描界面都是全屏会话,不内嵌在 RN 页面内,需由点击触发面或调用 ref.startScan() / ref.capture() 显式拉起。
  • 会话期间的 JS:会话进行中 RN 页面处于后台,JS 定时器暂停、事件回调照常到达;会话中的 capture() 请在事件回调中调用。
  • 回调时机:onPictureTaken 在会话结束时逐张触发,而非每拍一张立即触发;需要在会话中立即拿到某一张时,使用会话中 capture() 的返回值。
  • Vision Kit 引擎:拍摄模式默认自动、滤镜默认原图(彩色),扫描界面无相册导入与分享入口;不回传裁剪前原图与四角坐标,不触发 onRectangleDetect,取景微调属性不生效,会话中不支持 capture()。
  • 自建取景引擎:边框检测为独立实现,同一场景下检出的边框可能与 iOS 不同;rectangleCoordinates 为拍照图像素坐标,数值不与 iOS 逐位可比;切换前后摄像头后会按 enableTorch 重新设置手电筒;拍照时不会额外触发一次 onRectangleDetect。
  • 连续拍摄:captureMultiple 为 true 时单次会话最多 maxShotCount 张(缺省 9),上游不限张数。
  • 结果图处理:brightness / saturation / contrast / quality 在拍摄完成后作用于结果图,不改变取景预览画面;quality 未传时不重新编码。
  • 文件形态:文件结果为 file:// URI;Base64 结果不含换行。
  • 1.4.3 才引入的上游属性(noGrayScale / documentAnimation / saveInAppDocument / onProcessing / onPermissionsDenied)不在本包 API 面内;manualOnly 按 1.4.3 语义作为本端新增属性提供,缺省 false 时行为与 1.4.2 一致。

开源license

本项目基于 MIT 协议,详见 LICENSE 文件,与上游 react-native-document-scanner 保持一致。

问题反馈渠道

如果在使用过程中遇到任何问题,欢迎通过 GitCode 仓库与 Issue 反馈:

https://gitcode.com/hxa-rn/react-native-document-scanner

https://gitcode.com/hxa-rn/react-native-document-scanner/issues

Introduction

实时文档扫描与裁剪

Customize your domain