更新记录

1.19.2(2026-07-20)

补充readme.md文档说明

1.19.1(2026-07-19)

  • ·重要:·新增组件模式,可以在页面以组件的方式引用插件

1.19.0(2026-07-04)

  • 修复:安卓端在连续扫码的情况下偶发性的黑屏问题
  • 修复:安卓端在连续扫码的情况下偶发性的无法识别问题
  • 细节优化
查看更多

平台兼容性

uni-app(4.66)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
- - - - 6.0 15 -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

uni-app x(4.66)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - 6.0 15 11 -

其他

多语言 暗黑模式 宽屏模式
× ×

插件使用说明文档

注意!

插件需要打自定义基座运行!

插件需要打自定义基座运行!

插件需要打自定义基座运行!

插件功能说明

  • 支持多种码类型识别,可参考下面的码类型说明
  • 支持单码/多码识别
  • 支持连续扫码场景
  • 支持界面图标自定义
  • 支持识别成功提示音和震动效果
  • 连续扫码场景支持自定义识别成功toast提示文案
  • 支持自动缩放和双指缩放
  • 支持在页面以组件的形式调用,具体使用参考下面的示例部分

IOS端注意!,不支持摄像头切换,用法参考后面的用例(扫码插件支持的ios版本是>=15.5)

鸿蒙端注意:鸿蒙使用的是官方默认扫码界面UI,不支持自定义界面内容,只能单码识别,不支持连续扫码

扫码类型:支持文本、链接、电话、邮件、WIFI等通用类型条码

type CodeType = 'text'| 'url'| 'wifi'| 'phone'| 'sms'
| 'email'
| 'contact'
| 'geo'
| 'calendar'
| 'driverLicense'
| 'isbn'
| 'product';

支持扫码格式列表,默认支持全部格式,可以设置单个或多个扫码格式类型,不设置默认是0,支持全部扫码格式


  • 0----->代表全部格式
  • 1----->FORMAT_CODE_128
  • 2----->FORMAT_CODE_39
  • 4----->FORMAT_CODE_93
  • 8----->FORMAT_CODABAR
  • 32---->FORMAT_EAN_13
  • 64---->FORMAT_EAN_8)
  • 128--> FORMAT_ITF) 二维码
  • 256--> FORMAT_QR_CODE 二维码
  • 512--->FORMAT_UPC_A
  • 1024-->FORMAT_UPC_E
  • 2048-->FORMAT_PDF417
  • 16---->FORMAT_DATA_MATRIX
  • 4096-->FORMAT_AZTEC

  • 参数说明
属性 类型 默认值 必填 描述
cameraType string BACK - 开启前置摄像头,不设置默认使用后置摄像头BACK,当设备只有一个摄像头,该设置无效,会自动取可用列表的摄像头
continuous boolean false - 设为true即可开启连续扫码,默认不开启
continuousDelay number 800 - 连续扫码场景,间隔时间
autoZoom boolean false - 开启相机自动缩放,默认不开启,只限非连续扫码模式下使用
cameraRotation number null - 预览纠偏角度,仅 Android 生效,可选 0/90/180/270,用于修正部分硬件预览画面倒立或横转问题(非必要不要设置该字段)
styleFollowIos boolean true - 页面样式是否跟随IOS端, 默认true,此为全屏模式(与scanBox模式二选一)
showLamplight boolean true - 隐藏/显示灯光操作,默认显示
showPhotoAlbum boolean true - 隐藏/显示相册操作,默认显示
scanBox boolean false - 中间区域扫码模式,默认关闭,(注意:如果开启此模式,styleFollowIos必须配置且为false)
scanBoxTitle string '将码放入取景框,即可自动扫描' - 中间区域扫码模式标题,只有scanBox为true生效
scanBoxTitleColor string '#ffffff' - 中间区域扫码模式标题颜色,只有scanBox为true生效
scanBoxTitleSize number 16 - 中间区域扫码模式标题大小,只有scanBox为true生效
scanBoxHeight number 540 - 中间区域扫码框的高度,只有scanBox为true生效
formatsVal string '0' - 设置扫码的制式,默认为'0',支持全部制式
markeTitle string '#ffffff' - 设置扫码页底部识别中的提示文字,默认值正在识别中,请稍后...
showToast boolean false - 二维码识别成功显示toast(只针对连续扫码生效)
showToastText string '自定义扫码成功提示' - 设置连续扫码场景成功提示语
lightOnText string '灯光打开' - 自定义打开灯光文案
lightOffText string '灯光关闭' - 自定义关闭灯光文案
photoText string '自定义相册文字' - 相册底部文案(只针对安卓不跟随IOS端界面样式有效)
moreQrCodeSelectText string '识别到多个二维码,请选择一个打开' - 多个二维码选择提示文案
moreQrCodeSelectTextColor string '#ffffff' - 多个二维码选择提示文案颜色
moreQrCodeSelectTextSize number 16 - 多个二维码选择提示文案大小
outputAllCodeData |boolean false - 开启后,直接返回扫码数据,获取返回值内容需要取optionArr字段,默认关闭(只针对全屏扫码且非连续扫码有效)
customFailToatText string 未识别到二维码 - 未识别到二维码时提示内容
firstUseUltraWideCamera boolean false - 针对IOS 13以上机型使用,优先使用超广角相机识别二维码(适合近距离扫码场景,非此场景不要设置该字段)
timeoutPeriod number 20 - 识别超时时间,默认20S
openSound boolean true - 是否开启识别成功音效,默认开启
defaultOpenLight boolean false - 是否默认开启手电筒,默认不开启

方法说明

  • openCamera 打开扫码页
  • closeCamera 主动关闭扫码页
  • setContinuousScanStatus 设置暂停扫码或继续扫码,针对连续扫码场景
  • warmupCameraProvider 针对外接摄像头启动比较慢的情况可以在页面初始化时调用这个相机预热方法(仅需一次),可以提高打开相机时间
  • scanImageByPath 直接识别本地图片中的二维码/条形码,不打开扫码页(当前仅 Android 支持)

App 内嵌扫码组件说明

插件同时提供 API 全屏扫码和组件内嵌扫码两种形态。组件是对现有 API 插件的补充扩展,不改变 openCameracloseCamerasetContinuousScanStatusscanImageByPathwarmupCameraProvider 的现有行为。

组件标签

<xwq-mlkit-scan-code-view
    style="width: 100%; height: 420rpx;"
    :continuous="true"
    :auto-start="true"
    formats-val="0"
    @success="onScanSuccess"
    @error="onScanError"
/>

组件平台说明

项目类型 Android App iOS App 说明
uni-app x 支持 支持 使用标准 native-view 承载原生相机预览
uni-app 普通 Vue 页面 不支持内嵌 不支持内嵌 普通 Vue 页面不支持 native-view,组件会触发 unsupported/error 事件
uni-app nvue/兼容模式 支持 支持 使用 utssdk/app-android/index.vueutssdk/app-ios/index.vue 的兼容模式原生组件入口

组件属性

属性 类型 默认值 描述
autoStart boolean true 原生容器初始化后是否自动启动扫码
continuous boolean false 是否连续扫码
continuousDelay number 800 连续扫码回调间隔
formatsVal string '0' 识别格式,规则与 openCamera 一致
cameraType string 'BACK' 摄像头方向,BACK/FRONT
defaultOpenLight boolean false 是否默认打开手电筒
scanBox boolean false 是否开启中间扫码框模式。开启后 App Android/iOS 组件侧只识别扫码框内图像
scanBoxTitle string '将码放入取景框,即可自动扫描' 扫码框提示文案,当前组件原生覆盖层主要使用扫码框和裁剪逻辑,提示文案预留给组件 UI 使用
scanBoxHeight number 200 扫码框高度,单位 px,只有 scanBox=true 时生效

组件事件

事件 描述
ready 原生扫码容器初始化完成
start 调用 start()autoStart=true 自动启动扫码后触发
stop 调用 stop() 停止扫码后触发
success 识别成功,返回结构与 CallbackValType 一致
error 识别失败或启动失败
unsupported 当前页面或平台不支持内嵌扫码
stateChange 组件状态变化,返回 startstoppauseresume

uni-app nvue 兼容模式中,自定义事件参数按 UTS 组件规范使用 Map<string, any> 包装,业务层从 detail 中取真实数据:

onScanSuccess(e) {
    const detail = e.get ? e.get('detail') : e.detail
    console.log('nvue 内嵌扫码结果', detail)
}

组件方法

可通过 ref 调用:start()stop()pause()resume()setTorch(enabled)

方法 说明 典型使用场景
start() 启动内嵌扫码;如果之前调用过 stop(),可用该方法恢复相机会话和预览层 自动启动、手动开始扫码、停止后再次扫码
pause() 只暂停识别帧处理,不释放相机和预览 单次扫码后保留相机画面、等待业务处理完成后继续扫码
resume() 恢复识别帧处理;如果当前相机会话已被 stop() 释放,会尝试按上次参数重新启动 暂停后继续扫码
stop() 停止相机采集并移除预览层;组件卸载时才完整释放相机资源 用户点击停止、页面内临时关闭预览
setTorch(enabled) 打开或关闭手电筒 自定义灯光按钮

pause()stop() 的区别:pause() 只是停止识别,保留相机预览;stop() 会停止采集并移除预览层,后续可调用 start() 恢复。iOS 内嵌组件为避免频繁释放 AVCaptureSession 引发系统层竞态,点击 stop() 不会立刻销毁相机会话,组件卸载时会自动完整释放资源。

nvue 页面完整控制示例

uni-app nvue 兼容模式下,success/error 事件参数会以 Map 包装。建议使用一个取值工具方法兼容 Map.get() 和普通对象,并在页面侧维护运行状态,避免 stop() 后已经排队的异步 success 继续进入业务逻辑。

<template>
    <view style="flex: 1;">
        <xwq-mlkit-scan-code-view
            ref="scanCodeViewRef"
            style="width: 100%; height: 450rpx;"
            :continuous="continuous"
            :auto-start="true"
            formats-val="0"
            @success="onScanSuccess"
            @error="onScanError"
        />

        <button @click="startScan">开始扫码</button>
        <button @click="pauseScan">暂停扫码</button>
        <button @click="resumeScan">恢复扫码</button>
        <button @click="stopScan">停止扫码</button>
    </view>
</template>

<script>
export default {
    data() {
        return {
            result: [],
            continuous: false,
            // 页面侧运行标记,用于忽略 stop 后才到达的异步 success。
            isScanRunning: true
        }
    },
    methods: {
        // nvue 事件可能是 Map,也可能是普通对象,统一通过该方法取字段。
        getEventField(target, key) {
            return target && target.get ? target.get(key) : (target ? target[key] : null)
        },
        onScanSuccess(e) {
            if (!this.isScanRunning) return

            const payload = e.get ? e.get('detail') : e.detail
            const detail = this.getEventField(payload, 'detail') ? this.getEventField(payload, 'detail') : payload
            const option = this.getEventField(detail, 'option')
            const textVal = this.getEventField(option, 'textVal') || ''
            this.result.push(textVal)

            if (this.continuous == false) {
                // 单次扫码:识别成功后暂停后续识别,保留当前预览。
                this.$refs.scanCodeViewRef.pause()
            }
        },
        onScanError(e) {
            const detail = e.get ? e.get('detail') : e.detail
            console.log('nvue 内嵌扫码错误', detail)
        },
        startScan() {
            this.isScanRunning = true
            this.$refs.scanCodeViewRef.start()
        },
        pauseScan() {
            this.$refs.scanCodeViewRef.pause()
        },
        resumeScan() {
            this.$refs.scanCodeViewRef.resume()
        },
        stopScan() {
            // 先更新页面状态,再停止组件,避免后到 success 继续执行业务逻辑。
            this.isScanRunning = false
            this.$refs.scanCodeViewRef.stop()
        }
    }
}
</script>

uvue 页面完整控制示例

uni-app x 的 uvue 页面中,内嵌组件事件在 App 端存在平台差异:Android 回调参数是 Map<string, any>,真实扫码数据在 e.get('detail') 中;iOS 回调参数是 UniEvent,真实扫码数据在 e.detail 中。建议先统一解析为 CallbackValType 后再进入业务逻辑。如果是单次扫码,可以在 success 回调里调用 pause() 暂停识别;如果用户手动点击停止,调用 stop() 会停止采集并移除预览层,后续可继续调用 start() 恢复。

<template>
    <view class="page">
        <xwq-mlkit-scan-code-view
            ref="scanCodeViewRef"
            class="scan-view"
            :continuous="continuous"
            :auto-start="true"
            formats-val="0"
            @success="onScanSuccess"
            @error="onScanError"
        />

        <view class="scan-code-btn">
            <button class="tool-btn" @click="startScan">开始扫码</button>
            <button class="tool-btn" @click="pauseScan">暂停扫码</button>
            <button class="tool-btn" @click="resumeScan">恢复扫码</button>
            <button class="tool-btn" @click="stopScan">停止扫码</button>
        </view>

        <scroll-view :scroll-y="true" class="result-wrap">
            <view v-for="(item, index) in result" :key="index" class="result-item">
                <text>{{ index + 1 }}. {{ item }}</text>
            </view>
        </scroll-view>
    </view>
</template>

<script setup lang="uts">
import { ref } from 'vue'
import { CallbackValType, ErrorCallbackValType, OptionType } from '@/uni_modules/xwq-mlkit-scan-code/utssdk/interface.uts'

const scanCodeViewRef = ref<XwqMlkitScanCodeViewElement | null>(null)
const result = ref<string[]>([])
const continuous = ref<boolean>(false)
const isScanRunning = ref<boolean>(true)

function parseScanSuccessEvent(value : any) : CallbackValType {
    // #ifdef APP-ANDROID
    const eventMap = value as Map<string, any>
    const detail = eventMap.get('detail') as Map<string, any>
    const optionMap = detail.get('option') as Map<string, any>
    const option : OptionType = {
        textVal: optionMap.get('textVal') as string,
        type: optionMap.get('type') as string,
        scanCodeType: optionMap.get('scanCodeType') as string
    }
    const result : CallbackValType = {
        type: detail.get('type') as string,
        scanCodeType: detail.get('scanCodeType') as string,
        option: option
    }
    return result
    // #endif
    // #ifdef APP-IOS
    const event = value as UniEvent
    const detail = event.detail as UTSJSONObject
    const optionMap = detail['option'] as UTSJSONObject
    const option : OptionType = {
        textVal: optionMap['textVal'] as string,
        type: optionMap['type'] as string,
        scanCodeType: optionMap['scanCodeType'] as string
    }
    const result : CallbackValType = {
        type: detail['type'] as string,
        scanCodeType: detail['scanCodeType'] as string,
        option: option
    }
    return result
    // #endif
    // #ifndef APP-ANDROID
    // #ifndef APP-IOS
    return value as CallbackValType
    // #endif
    // #endif
}

function parseScanErrorEvent(value : any) : ErrorCallbackValType {
    // #ifdef APP-ANDROID
    const eventMap = value as Map<string, any>
    const detail = eventMap.get('detail') as Map<string, any>
    const error : ErrorCallbackValType = {
        type: detail.get('type') as string,
        msg: detail.get('msg') as string
    }
    return error
    // #endif
    // #ifdef APP-IOS
    const event = value as UniEvent
    const detail = event.detail as UTSJSONObject
    const error : ErrorCallbackValType = {
        type: detail['type'] as string,
        msg: detail['msg'] as string
    }
    return error
    // #endif
    // #ifndef APP-ANDROID
    // #ifndef APP-IOS
    return value as ErrorCallbackValType
    // #endif
    // #endif
}

function onScanSuccess(value : any) {
    if (!isScanRunning.value) return

    const scanResult = parseScanSuccessEvent(value)
    const textVal = scanResult.option.textVal ?? ''
    result.value.push(textVal)

    if (continuous.value == false) {
        // 单次扫码:识别成功后暂停后续识别,保留当前预览。
        scanCodeViewRef.value?.pause()
    }
}

function onScanError(value : any) {
    console.log('uvue 内嵌扫码错误', parseScanErrorEvent(value))
}

function startScan() {
    isScanRunning.value = true
    scanCodeViewRef.value?.start()
}

function pauseScan() {
    scanCodeViewRef.value?.pause()
}

function resumeScan() {
    scanCodeViewRef.value?.resume()
}

function stopScan() {
    // 先更新页面状态,再停止组件,避免后到 success 继续执行业务逻辑。
    isScanRunning.value = false
    scanCodeViewRef.value?.stop()
}
</script>

<style>
.page {
    flex: 1;
}

.scan-view {
    width: 100%;
    height: 450rpx;
}

.scan-code-btn {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: center;
    padding: 20rpx;
}

.tool-btn {
    margin-right: 10rpx;
}

.result-wrap {
    flex: 1;
    padding: 30rpx;
}

.result-item {
    padding: 12rpx 0;
}
</style>

单次扫码:识别成功后暂停识别

适合需要保留相机预览,业务处理完成后还可能继续扫码的场景。

<template>
    <view style="flex: 1;">
        <xwq-mlkit-scan-code-view
            ref="scanCodeViewRef"
            style="width: 100%; height: 600px;"
            :continuous="true"
            :auto-start="true"
            formats-val="0"
            @success="onScanSuccess"
            @error="onScanError"
        />
        <button @click="resumeScan">继续扫码</button>
    </view>
</template>

<script>
export default {
    methods: {
        onScanSuccess(e) {
            const detail = e.get ? e.get('detail') : e.detail
            console.log('扫码结果', detail)

            // 单次扫码:暂停后续识别,但保留相机预览
            this.$refs.scanCodeViewRef.pause()
        },
        onScanError(e) {
            const detail = e.get ? e.get('detail') : e.detail
            console.log('扫码错误', detail)
        },
        resumeScan() {
            this.$refs.scanCodeViewRef.resume()
        }
    }
}
</script>

单次扫码:识别成功后释放相机

适合识别成功后不再需要相机、希望立刻释放摄像头占用的场景。

<template>
    <view style="flex: 1;">
        <xwq-mlkit-scan-code-view
            ref="scanCodeViewRef"
            style="width: 100%; height: 600px;"
            :continuous="true"
            :auto-start="true"
            formats-val="0"
            @success="onScanSuccess"
            @error="onScanError"
        />
        <button @click="startScan">重新扫码</button>
    </view>
</template>

<script>
export default {
    methods: {
        onScanSuccess(e) {
            const detail = e.get ? e.get('detail') : e.detail
            console.log('扫码结果', detail)

            // 释放相机资源和预览层
            this.$refs.scanCodeViewRef.stop()
        },
        onScanError(e) {
            const detail = e.get ? e.get('detail') : e.detail
            console.log('扫码错误', detail)
        },
        startScan() {
            this.$refs.scanCodeViewRef.start()
        }
    }
}
</script>

连续扫码:业务处理期间临时暂停

连续扫码时,如果每次识别成功后需要请求接口或弹窗确认,建议先调用 pause(),业务完成后再 resume(),避免同一个码短时间内重复触发多次。

onScanSuccess(e) {
    const detail = e.get ? e.get('detail') : e.detail
    this.$refs.scanCodeViewRef.pause()

    // 模拟业务处理,完成后继续识别
    setTimeout(() => {
        this.$refs.scanCodeViewRef.resume()
    }, 1500)
}
<template>
    <view style="flex: 1;">
        <xwq-mlkit-scan-code-view
            ref="scanView"
            style="width: 100%; height: 420rpx;"
            :continuous="false"
            @success="onScanSuccess"
            @error="onScanError"
        />
        <button @click="pauseScan">暂停</button>
        <button @click="resumeScan">继续</button>
    </view>
</template>

<script setup lang="uts">
import { ref } from 'vue'

const scanView = ref<XwqMlkitScanCodeViewComponentPublicInstance | null>(null)

function onScanSuccess(value : any) {
    console.log('内嵌扫码结果', value)
}

function onScanError(value : any) {
    console.log('内嵌扫码失败', value)
}

function pauseScan() {
    scanView.value?.pause()
}

function resumeScan() {
    scanView.value?.resume()
}
</script>

注意事项

  • 组件模式同一时间只允许一个扫码实例占用相机。
  • 不建议在组件运行时同时调用 openCamera(),否则可能触发相机占用错误。
  • 页面离开或组件卸载时会自动释放相机资源。
  • 普通 uni-app Vue 页面不能真正内嵌原生预览;uni-app 项目请在 nvue 页面中使用组件,如需普通 Vue 页面扫码请继续使用 API 模式。

cameraRotation 常见硬件异常与推荐取值

  • 正常设备预览方向正确:cameraRotation 不传或传 0
  • 预览画面倒立 180 度:传 cameraRotation: 180
  • 预览画面顺时针旋转 90 度:传 cameraRotation: 90
  • 预览画面逆时针旋转 270 度:传 cameraRotation: 270
  • 建议先在异常设备上逐个测试 90/180/270,以“用户看到的预览画面为正”为准
  • 该字段当前用于纠正 Android 预览层显示方向,不影响页面 UI 朝向

Web 端扫码说明

实现方式

  • Web 端扫码基于 @zxing/library 实现。
  • 当前 Web 端相机识别使用 takePhoto() 抓拍单帧图片后再交给 ZXing 解码,不是 App 端那种原生相机实时识别链路。
  • 相册识别直接使用整张图片解码,因此通常会比 Web 相机识别更稳定。

性能与体验限制

  • Web 端性能明显弱于 App 端原生扫码,识别速度、流畅度、稳定性都不如 App 端。
  • Web 端相机识别依赖浏览器/运行容器提供的拍照与摄像头能力,不同设备和不同内核表现差异较大。
  • 因为当前是抓拍单帧后识别,所以页面会存在轻微卡顿,识别速度也会慢于原生实时扫码。
  • Web 端存在方向、镜像、分辨率压缩等兼容性问题,部分设备上会影响识别成功率。

支持的码类型

  • 按 ZXing 官方仓库 README 的 Supported Formats 说明,Web 解码能力覆盖以下类型:

1D 商品码

  • UPC_A
  • UPC_E
  • EAN_8
  • EAN_13

1D 工业码

  • CODE_39
  • CODE_93
  • CODE_128
  • CODABAR
  • ITF
  • RSS_14
  • RSS_EXPANDED(官方标注为 not production ready)

2D 码

  • QR_CODE

  • DATA_MATRIX

  • AZTEC

  • PDF_417

  • MAXICODE(ZXing 官方 README 中已标注为未支持)

  • 当前插件 Web 端 formatsVal 参数已对接并开放配置的格式,仍以本插件前面的格式枚举列表为准。

已知限制

  • Web 端对小二维码、远距离二维码、低对比度二维码识别效果较差。
  • Web 端对密度很高或尺寸很小的二维码命中率不稳定。
  • 某些浏览器/运行容器里,只有部分一维码会更容易识别,二维码和复杂码型识别率可能下降。
  • 当环境对相机帧做了裁切、压缩或镜像处理时,识别效果会进一步变差。
  • 如果业务场景对扫码速度和成功率要求高,建议优先使用 App 端扫码能力。

使用建议

  • 优先保证二维码尺寸足够大,并尽量放在画面中央。
  • 尽量使用清晰、对比度高、无遮挡的码图。
  • Web 端更适合作为功能补充,不建议作为高强度连续扫码主场景。

识别成功回调参数说明

CallbackValType:{
    type --- 识别码内容类型 例如文本-text  链接-url 商品-product
    option ----{
        textVal?:string ------- 文本值
        url?:string --------- 链接
        phone?:string -------- 手机号
        proNumber?:string ----- 商品编号
    }
    optionArr ----  当初始化配置outputAllCodeData设置为true时,该字段才有值,内容字段和option字段一致
    scanCodeType ----- 识别码为二维码/条形码 1- 二维码  2- 条形码 0- 未知 (当outputAllCodeData设置为true时,该字段会包含在optionArr的每个子项中)
}

optionArr字段参数说明:{
    emailAddress ---------邮件地址
    ssid------------------wifi账号
    password--------------wifi密码
    phone-----------------手机号
    proNumber-------------产品编号
    rect------------------二维码坐标信息
        {
            bottom--------底部坐标
            left----------左边坐标
            right---------右边坐标
            top-----------顶部坐标
        }
    scanCodeType----------识别码类型 1- 二维码  2- 条形码 0- 未知
    textVal---------------识别内容
    type------------------码内容类型
    url-------------------url码内容结果
}

页面调用插件方式

直接识别本地图片

属性 类型 默认值 必填 描述
path string '' 本地图片地址,当前 Android 侧尽量兼容绝对路径、file://content:// 等格式
formatsVal string '0' 设置识别格式,规则与 openCameraformatsVal 一致,多个格式用英文逗号分隔
outputAllCodeData boolean false 开启后直接返回图片中全部识别结果,需从 optionArr 字段取值
success function - 识别成功回调,返回结构与 openCamera 保持一致
error function - 识别失败回调,包含路径无效、图片解码失败、未识别到二维码等错误信息
import { scanImageByPath } from '@/uni_modules/xwq-mlkit-scan-code'

/**
 * 本地图片识别
 */
uni.getImageInfo({
    src: imageUrl.value,
    success: (res) => {
        console.log('本地临时路径:', res)

        scanImageByPath({
            path: res.path,
            formatsVal: '256,32',
            outputAllCodeData: true,
            success: (val) => {
                console.log('图片识别结果', val)
            },
            error: (err) => {
                console.log('图片识别失败', err)
            }
        })
    }
})

/**
 * 网络图片识别
 */
uni.downloadFile({
    url: imageUrl.value,
    success: (downloadRes) => {
        if (downloadRes.statusCode === 200) {
            const localPath = downloadRes.tempFilePath
            console.log('获取到的本地图片路径:', localPath)

            scanImageByPath({
                path: localPath,
                formatsVal: '256,32',
                outputAllCodeData: false,
                success: (val) => {
                    console.log('图片识别结果', val)
                },
                error: (err) => {
                    console.log('图片识别失败', err)
                }
            })
        }
    },
    fail: (err) => {
        console.error('下载失败', err)
        uni.hideLoading()
        uni.showToast({ title: '图片处理失败', icon: 'error' })
    }
})
  • scanImageByPath 当前已支持 AndroidiOSHarmonyWeb 会返回 UNSUPPORTED_PLATFORM
  • outputAllCodeDatafalse 时,默认只返回首个识别结果
  • outputAllCodeDatatrue 时,完整结果位于 optionArr

scanImageByPath error 回调说明

type 含义 典型场景
PARAM_ERROR 参数错误 未传 path,或传入空字符串
DECODE_ERROR 图片解析失败 路径无效、文件不存在、图片无法解码、权限受限
EMPTY_RESULT 未识别到二维码 图片可正常读取,但 ML Kit 没有识别出有效码
SCAN_ERROR 识别过程异常 ML Kit 识别阶段抛出异常
UNSUPPORTED_PLATFORM 当前平台未实现 HarmonyWeb 调用该接口
  • uniapp的使用方式

<template>
    <view>
        <button @click="openScan">打开扫码</button>
    </view>
</template>

<script>
    import {openCamera,closeCamera,setContinuousScanStatus} from '@/uni_modules/xwq-mlkit-scan-code';
    export default {
        methods: {
            openScan(){
                openCamera({
                    cameraType:"FRONT",//开启前置摄像头,不设置默认使用后置摄像头,当设备只有一个摄像头,该设置无效,会自动取可用列表的摄像头
                    continuous:true,//设为true即可开启连续扫码,默认不开启
                    continuousDelay:2000,//连续扫码间隔时间
                    autoZoom:true,//开启相机自动缩放,默认不开启,只限非连续扫码模式下使用
                    cameraRotation:0,//预览纠偏角度,仅 Android 生效;例如硬件预览逆时针旋转270度时可传 270 纠正(非必要不要设置该字段)
                    styleFollowIos:false, //页面样式是否跟随IOS端, 默认true,此为全屏模式(与scanBox模式二选一)
                    showLamplight:false,//隐藏灯光操作,默认显示
                    showPhotoAlbum:false,//隐藏相册操作,默认显示
                    scanBox:true, //中间区域扫码模式 (注意:如果开启此模式,styleFollowIos必须配置且为false)
                    scanBoxTitle:'将码放入取景框,即可自动扫描',//中间区域扫码模式标题,只有scanBox为true生效
                    scanBoxTitleColor:"#ff0000",//中间区域扫码模式标题颜色,只有scanBox为true生效
                    scanBoxTitleSize:16,//中间区域扫码模式标题大小,只有scanBox为true生效
                    scanBoxHeight:200, //中间区域扫码框的高度,只有scanBox为true生效
                    formatsVal:'32,128,256', //扫码格式
                    markeTitle:'', //扫码页底部提示文字
                    showToast:false,//二维码识别成功显示toast(只针对连续扫码生效)
                    showToastText:"自定义扫码成功提示",//连续扫码场景提示语
                    customFailToatText:"自定义未识别到二维码信息", //未识别到二维码时提示内容
                    lightOnText:'灯光打开',//自定义打开灯光文案
                    lightOffText:'灯光关闭',//自定义关闭灯光文案
                    photoText: "自定义相册文字",//相册底部文案
                    moreQrCodeSelectText:"当前识别到多个二维码,请选择一个", //多个二维码选择提示文案
                    moreQrCodeSelectTextColor:"#ff0000", //多个二维码选择提示文案颜色
                    moreQrCodeSelectTextSize:18, //多个二维码选择提示文案大小
                    outputAllCodeData:false, //开启后,直接返回扫码数据,获取返回值内容需要取optionArr字段,默认关闭(只针对全屏扫码且非连续扫码有效)
                    success:(val)=>{
                        console.log('扫码结果回调===',val)
                        // 返回参数增加scanCodeType 识别码类型 1- 二维码  2- 条形码 0- 未知
                        //暂停扫码(针对连续扫码场景生效)
                        // setContinuousScanStatus(true)

                        // if(val.optionArr!=null&&val.optionArr!.length>0){
                        //  val.optionArr?.forEach(item=>{
                        //      result.value.push(item.textVal ?? '');
                        //  })
                        // }else{
                        //  result.value.push(val.option.textVal ?? '');
                        // }

                        // setTimeout(()=>{
                            //接口识别后,继续扫码
                        //  setContinuousScanStatus(false)
                        // },5000)
                    },
                    error:(val) => {
                        console.log('识别失败===', val);
                        uni.showToast({
                            title:"没有识别到二维码"
                        })
                    },
                    cancel:()=>{
                        console.log('取消扫码')
                    }
                });
            },
        }
    }
</script>
  • uniappX的使用方式

<template>
    <view>
        <button @click="openScan">打开扫码</button>
    </view>
</template>

<script lang='uts'>
    import {openCamera,closeCamera,setContinuousScanStatus} from '@/uni_modules/xwq-mlkit-scan-code';
    import { InitParamsType, CallbackValType,ErrorCallbackValType } from '@/uni_modules/xwq-mlkit-scan-code/utssdk/interface.uts';
    export default {
        data() {
            return {}
        },
        methods: {
            openScan(){
                openCamera({
                    cameraType:"FRONT",//开启前置摄像头,不设置默认使用后置摄像头,当设备只有一个摄像头,该设置无效,会自动取可用列表的摄像头
                    continuous:true,//设为true即可开启连续扫码,默认不开启
                    continuousDelay:2000,//连续扫码间隔时间
                    autoZoom:true,//开启相机自动缩放,默认不开启,只限非连续扫码模式下使用
                    cameraRotation:270,//预览纠偏角度,仅 Android 生效;例如硬件预览逆时针旋转270度时可传 270 纠正(非必要不要设置该字段)
                    styleFollowIos:false, //页面样式是否跟随IOS端, 默认true,此为全屏模式(与scanBox模式二选一)
                    showLamplight:false,//隐藏灯光操作,默认显示
                    showPhotoAlbum:false,//隐藏相册操作,默认显示
                    scanBox:true, //中间区域扫码模式 (注意:如果开启此模式,styleFollowIos必须配置且为false)
                    scanBoxTitle:'将码放入取景框,即可自动扫描',//中间区域扫码标题,只有scanBox为true生效
                    scanBoxTitleColor:"#ff0000",//中间区域扫码标题颜色,只有scanBox为true生效
                    scanBoxTitleSize:16,//中间区域扫码标题大小,只有scanBox为true生效
                    scanBoxHeight:200, //中间区域扫码框的高度,只有scanBox为true生效
                    formatsVal:'32,128,256', //扫码格式
                    markeTitle:'', //扫码页底部提示文字
                    showToast:false,//二维码识别成功显示toast(只针对连续扫码生效)
                    showToastText:"自定义扫码成功提示",//连续扫码场景提示语
                    customFailToatText:"自定义未识别到二维码信息", //未识别到二维码时提示内容
                    lightOnText:'灯光打开',//自定义打开灯光文案
                    lightOffText:'灯光关闭',//自定义关闭灯光文案
                    photoText: "自定义相册文字",//相册底部文案
                    moreQrCodeSelectText:"当前识别到多个二维码,请选择一个", //多个二维码选择提示文案
                    moreQrCodeSelectTextColor:"#ff0000", //多个二维码选择提示文案颜色
                    moreQrCodeSelectTextSize:18, //多个二维码选择提示文案大小
                    outputAllCodeData:false, //开启后,直接返回扫码数据,获取返回值内容需要取optionArr字段,默认关闭(只针对全屏扫码且非连续扫码有效)
                    success:(val:CallbackValType)=>{
                        console.log('扫码结果回调===',val)
                        //暂停扫码(针对连续扫码场景生效)
                        // setContinuousScanStatus(true)
                        // 返回参数增加scanCodeType 识别码类型 1- 二维码  2- 条形码 0- 未知
                        // if(val.optionArr!=null&&val.optionArr!.length>0){
                        //  val.optionArr?.forEach(item=>{
                        //      result.value.push(item.textVal ?? '');
                        //  })
                        // }else{
                        //  result.value.push(val.option.textVal ?? '');
                        // }

                        // setTimeout(()=>{
                            //接口识别后,继续扫码
                        //  setContinuousScanStatus(false)
                        // },5000)
                    },
                    error:(val : ErrorCallbackValType) => {
                        console.log('识别失败===', val);
                        uni.showToast({
                            title:"没有识别到二维码"
                        })
                    },
                    cancel:()=>{
                        console.log('取消扫码')
                    }
                } as InitParamsType);
            },
        }
    }
</script>

IOS端UniappX项目中使用

<template>
    <view>
        <button @click="openScan">打开扫码</button>
    </view>
</template>

<script setup>
    import { openCamera,closeCamera,setContinuousScanStatus} from '@/uni_modules/xwq-mlkit-scan-code';
    import { InitParamsType, CallbackValType,ErrorCallbackValType } from '@/uni_modules/xwq-mlkit-scan-code/utssdk/interface.uts';
    const openScan = () => {
        openCamera({
            continuous:true,//设为true即可开启连续扫码,默认不开启
            continuousDelay:2000,//连续扫码间隔时间
            autoZoom:true,//开启相机自动缩放,默认不开启,只限非连续扫码模式下使用
            cameraRotation:270,//预览纠偏角度,仅 Android 生效;例如硬件预览逆时针旋转270度时可传 270 纠正(非必要不要设置该字段)
            styleFollowIos:false, //页面样式是否跟随IOS端, 默认true,此为全屏模式(与scanBox模式二选一)
            showLamplight:false,//隐藏灯光操作,默认显示
            showPhotoAlbum:false,//隐藏相册操作,默认显示
            formatsVal:'32,128,256', //扫码格式
            scanBox:true, //中间区域扫码模式 (注意:如果开启此模式,styleFollowIos必须配置且为false)
            scanBoxTitle:'将码放入取景框,即可自动扫描',//中间区域扫码标题,只有scanBox为true生效
            scanBoxTitleColor:"#ff0000",//中间区域扫码标题颜色,只有scanBox为true生效
            scanBoxTitleSize:16,//中间区域扫码标题大小,只有scanBox为true生效
            scanBoxHeight:200, //中间区域扫码框的高度,只有scanBox为true生效
            markeTitle:'', //扫码页底部提示文字
            showToast:false,//二维码识别成功显示toast(只针对连续扫码生效)
            showToastText:"自定义扫码成功提示",//连续扫码场景提示语
            customFailToatText:"自定义未识别到二维码信息", //未识别到二维码时提示内容
            lightOnText:'灯光打开',//自定义打开灯光文案
            lightOffText:'灯光关闭',//自定义关闭灯光文案
            photoText: "自定义相册文字",//相册底部文案
            moreQrCodeSelectText:"当前识别到多个二维码,请选择一个", //多个二维码选择提示文案
            moreQrCodeSelectTextColor:"#ff0000", //多个二维码选择提示文案颜色
            moreQrCodeSelectTextSize:18, //多个二维码选择提示文案大小
            outputAllCodeData:false, //开启后,直接返回扫码数据,获取返回值内容需要取optionArr字段,默认关闭(只针对全屏扫码且非连续扫码有效)
            success: (val : CallbackValType) => {
                console.log('识别结果====', val)
                //暂停扫码(针对连续扫码场景生效)
                // setContinuousScanStatus(true)
                // 返回参数增加scanCodeType 识别码类型 1- 二维码  2- 条形码 0- 未知
                // if(val.optionArr!=null&&val.optionArr!.length>0){
                //  val.optionArr?.forEach(item=>{
                //      result.value.push(item.textVal ?? '');
                //  })
                // }else{
                //  result.value.push(val.option.textVal ?? '');
                // }

                // setTimeout(()=>{
                    //接口识别后,继续扫码
                //  setContinuousScanStatus(false)
                // },5000)
            },
            error:(val : ErrorCallbackValType) => {
                console.log('识别失败===', val);
                uni.showToast({
                    title:"没有识别到二维码"
                })
            },
            cancel:()=>{
                console.log('取消扫码')
            }
        } as InitParamsType);

    };
</script>

在鸿蒙端使用用例(注意:鸿蒙使用的是官方默认扫码界面,不能自定义界面内容,只能单码识别,不支持连续扫码)

<template>
    <view>
        <button @click="openScan">打开扫码</button>
    </view>
</template>

<script setup>
    import { openCamera } from '@/uni_modules/xwq-mlkit-scan-code';
    import { InitParamsType, CallbackValType,ErrorCallbackValType } from '@/uni_modules/xwq-mlkit-scan-code/utssdk/interface.uts';
    const openScan = () => {
        openCamera({
            showPhotoAlbum:true,//相册入口是否开启
            success: (val : CallbackValType) => {
                console.log('识别结果====', val)
                uni.showToast({
                    title:'识别成功'
                })
            },
            error:(val : ErrorCallbackValType) => {
                console.log('识别失败===', val);
                uni.showToast({
                    title:"没有识别到二维码"
                })
            },
            cancel:()=>{
                console.log('取消扫码')
            }
        } as InitParamsType);

    };

其他插件预览

隐私、权限声明

1. 本插件需要申请的系统权限列表:

相机、相册

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率: