更新记录

1.0.0(2023-06-09)

新版首发


平台兼容性

Android Android CPU类型 iOS
适用版本区间:5.0 - 12.0 armeabi-v7a:支持,arm64-v8a:支持,x86:未测试 适用版本区间:11 - 15

原生插件通用使用流程:

  1. 购买插件,选择该插件绑定的项目。
  2. 在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块,如需要填写参数则参考插件作者的文档添加。
  3. 根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能。
  4. 打包自定义基座,选择插件,得到自定义基座,然后运行时选择自定义基座,进行log输出测试。
  5. 开发完毕后正式云打包

付费原生插件目前不支持离线打包。
Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/android
iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/ios

注意事项:使用HBuilderX2.7.14以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提示包名绑定不一致时,需要在HBuilderX项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件重新选择


KJ-HmsScan

华为统一扫码最新完整版、支持前置摄像头、持续扫码、生成解析条形码二维码、图片多码识别、完全自定义扫码界面(双端)

优惠价的插件,不支持前置摄像头,可以看:https://ext.dcloud.net.cn/plugin?id=12693

注意事项

1. <KJ-HmsScanV2> 完全自定义扫码界面,才支持前置摄像头,前置摄像头扫码成功率会降低,因为大部分都没有聚焦功能
2. andorid 前置摄像头扫码,不支持打开闪光灯

使用

<template>
    <view class="content">
        <button type="primary" @click="start">开始扫码(自带UI)</button>
        <view class="json">{{json}}</view>
        <button type="primary" @click="start2">跳转完全自定义扫码界面</button>
        <button type="primary" @click="decodeForImage">根据图片识别</button>
        <view class="json">{{json2}}</view>
        <button type="primary" @click="multiDecodeForImage">根据图片识别(多个码)</button>
        <view class="json">{{json3}}</view>
        <button type="primary" @click="generateCode">生成码图</button>
        <image :src="qrFilePath"></image>
    </view>
</template>

<script>
    var KJHmsScan = uni.requireNativePlugin("KJ-HmsScanV2");
    export default {
        data() {
            return {
                json: null,
                json2: null,
                json3: null,
                qrFilePath: null,
            }
        },
        onLoad() {
            if (plus.os.name == 'Android') {
                plus.android.requestPermissions(
                    ['android.permission.CAMERA',
                        "android.permission.READ_EXTERNAL_STORAGE"
                    ],
                    function(resultObj) {
                        var result = 0;
                        for (var i = 0; i < resultObj.granted.length; i++) {
                            var grantedPermission = resultObj.granted[i];
                            console.log('已获取的权限:' + grantedPermission);
                            result = 1
                        }
                        for (var i = 0; i < resultObj.deniedPresent.length; i++) {
                            var deniedPresentPermission = resultObj.deniedPresent[i];
                            console.log('拒绝本次申请的权限:' + deniedPresentPermission);
                            result = 0
                        }
                        for (var i = 0; i < resultObj.deniedAlways.length; i++) {
                            var deniedAlwaysPermission = resultObj.deniedAlways[i];
                            console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
                            result = -1
                        }
                    },
                    function(error) {
                        console.log('申请权限错误:' + error.code + " = " + error.message);
                    }
                );
            }
        },
        methods: {

            start() {
                /**
                 * scanTypes - 扫码类型 不传或为null的话,支持所有
                 * AZTEC CODABAR CODE_39 CODE_93 CODE_128 DATA_MATRIX EAN_8 EAN_13 ITF PDF_417 QR_CODE UPC_A UPC_E
                 * */
                var dic = {
                    //"scanTypes": ["CODE_128", "CODE_39"],
                    "viewType": 0 //0(设置扫码标题为“扫描二维码/条码”) 1(设置扫码标题为“扫描二维码”)
                }
                KJHmsScan.start(dic, (res) => {
                    console.log("start:" + JSON.stringify(res));
                    this.json = JSON.stringify(res)
                    /**
                     * 返回json字段说明:
                     * andorid:{"result":{"scanResult":"https://itunes.apple.com/cn/app/hello-uni-app/id1417078253","scanType":"QR_CODE",
                     * "other":{"showResult":"https://itunes.apple.com/cn/app/hello-uni-app/id1417078253","cornerPoints":[{"y":183,"x":17},{"y":16,"x":17},{"y":16,"x":183},{"y":182,"x":183}],
                     * "parserDic":{"theme":"","sceneType":"URL","linkValue":"https://itunes.apple.com/cn/app/hello-uni-app/id1417078253"},"scanTypeForm":1006}}}
                     * 
                     * ios:{"result":{"scanResult":"https://itunes.apple.com/cn/app/hello-uni-app/id1417078253",
                     * "other":{"zoomValue":1,"formatValue":"QR_CODE","time":"4","sceneType":"WebSite",
                     * "ResultPoint":[{"posY":"845.546120","posX":"38.256096"},{"posY":"77.935369","posX":"38.222356"},{"posY":"77.850768","posX":"393.087168"},
                     * {"posY":"846.450417","posX":"392.724744"}],"rawBytes":["xxx"],"text":"https://itunes.apple.com/cn/app/hello-uni-app/id1417078253",
                     * "numBits":480,"parserDic":{"url":"https://itunes.apple.com/cn/app/hello-uni-app/id1417078253","sceneType":"WebSite"},
                     * "exposureAdjustmentValue":0},"scanType":"QR_CODE"}}
                     * 
                     * ios和andorid共同字段:
                     * scanResult - 扫码结果
                     * scanType - 码类型
                     * other - 其它,sdk返回的其它信息
                     * */
                })
            },
            start2() {
                uni.navigateTo({
                    url: "scan"
                })
            },
            decodeForImage() {
                /**
                 * scanTypes - 扫码类型 不传或为null的话,支持所有
                 * AZTEC CODABAR CODE_39 CODE_93 CODE_128 DATA_MATRIX EAN_8 EAN_13 ITF PDF_417 QR_CODE UPC_A UPC_E
                 * */
                var dic = {
                    "scanTypes": ["CODE_128", "CODE_39", "QR_CODE"],
                    "filePath": plus.io.convertLocalFileSystemURL("static/oneCode.png")
                }
                KJHmsScan.decodeForImage(dic, (res) => {
                    console.log("decodeForImage:" + JSON.stringify(res));
                    this.json2 = JSON.stringify(res)
                })
            },
            multiDecodeForImage() {
                /**
                 * scanTypes - 扫码类型 不传或为null的话,支持所有
                 * AZTEC CODABAR CODE_39 CODE_93 CODE_128 DATA_MATRIX EAN_8 EAN_13 ITF PDF_417 QR_CODE UPC_A UPC_E
                 * */
                var dic = {
                    //"scanTypes": ["CODE_128", "CODE_39", "QR_CODE"],
                    "filePath": plus.io.convertLocalFileSystemURL("static/duoCode.png")
                }
                //注意事项: andorid版本识别多个码,不能全部识别出来,如果识别单个码,也识别不出来
                KJHmsScan.multiDecodeForImage(dic, (res) => {
                    console.log("multiDecodeForImage:" + JSON.stringify(res));
                    this.json3 = JSON.stringify(res)
                })
            },
            generateCode() {
                var dic = {
                    "scanType": "CODE_128",
                    "content": "KJ-HmsScan", //内容
                    "width": 200,
                    "height": 200,
                    "savePath": plus.io.convertLocalFileSystemURL("_doc/KJ-HmsScan"), //保存码图的路径
                    "format": "png", //保存的图片格式 有效值:png、jpeg
                    "quality": 100, //保存的图片质量,取值1-100, ios png 无效
                    /**以下参数,andorid才有效**/
                    "color": "#ff0000",
                    "bgColor": "#00FF00",
                    "margin": 3, //边距
                    //"QRLogoFilePath": plus.io.convertLocalFileSystemURL("static/logo.png"),
                    "errorCorrectionLevel": "L" //容错能力,L(可纠正约7%错误) ,M(可纠正约15%错误),Q(可纠正约25%错误),H(可纠正约30%错误)
                }
                KJHmsScan.generateCode(dic, (res) => {
                    console.log("generateCode:" + JSON.stringify(res));
                    this.qrFilePath = res.filePath;
                })
            }
        }
    }
</script>
<style>
    .json {
        word-wrap: break-word;
    }
</style>

完全自定义扫码界面nvue

    <template>
        <view class="content">
            <KJ-HmsScanV2 class="hmsScan" ref="hmsScan" :style="{width:'100%',height:palyerHeight}">
            </KJ-HmsScanV2>
            <view class="head" :style="{top:headTo}">
                <image class="back" src="../../static/back.png" @click="backClick"></image>
                <text class="text">扫一扫</text>
                <image class="album" src="../../static/scanAlbum.png" @click="albumClick"></image>
            </view>
            <view class="light" @click="lightClick">
                <image class="light_image" :src="isLightOn?'../../static/lightOn.png':'../../static/lightOff.png'"></image>
                <text class="text">{{isLightOn?'轻触关闭':'轻触照亮'}}</text>
            </view>
            <view class="btns">
                <button class="btn" type="primary" @click="init2">初始化扫码线效果</button>
                <button class="btn" type="primary" @click="init3">初始化扫码线效果2</button>
                <button class="btn" type="primary" @click="openFrontCamera">打开前置摄像头</button>
                <!-- <button class="btn" type="primary" @click="onScanForResult">监听扫码结果</button> -->
                <button class="btn" type="primary" @click="pauseContinuouslyScan">暂停持续扫码</button>
                <button class="btn" type="primary" @click="resumeContinuouslyScan">恢复持续扫码</button>
                <!-- <button class="btn" type="primary" @click="getLightStatus">获取闪光灯状态</button>
                <button class="btn" type="primary" @click="switchLight">切换闪光灯</button> -->
            </view>
        </view>
    </template>

    <script>
        var KJHmsScan = uni.requireNativePlugin("KJ-HmsScanV2");
        export default {
            data() {
                return {
                    palyerHeight: uni.getSystemInfoSync().screenHeight,
                    headTo: uni.getSystemInfoSync().statusBarHeight,
                    lightSrc: "../../static/ug_torch_off_img.png",
                    isLightOn: false,
                    json: null,
                    json2: null,
                    json3: null,
                    qrFilePath: null,
                }
            },
            onLoad() {
                var globalEvent = uni.requireNativePlugin('globalEvent');
                globalEvent.addEventListener('customizedScanDelegateForResult', function(e) {
                    console.log('customizedScanDelegateForResult' + JSON.stringify(e));
                });
                if (plus.os.name == 'Android') {
                    plus.android.requestPermissions(
                        ['android.permission.CAMERA',
                            "android.permission.READ_EXTERNAL_STORAGE"
                        ],
                        function(resultObj) {
                            var result = 0;
                            for (var i = 0; i < resultObj.granted.length; i++) {
                                var grantedPermission = resultObj.granted[i];
                                console.log('已获取的权限:' + grantedPermission);
                                result = 1
                            }
                            for (var i = 0; i < resultObj.deniedPresent.length; i++) {
                                var deniedPresentPermission = resultObj.deniedPresent[i];
                                console.log('拒绝本次申请的权限:' + deniedPresentPermission);
                                result = 0
                            }
                            for (var i = 0; i < resultObj.deniedAlways.length; i++) {
                                var deniedAlwaysPermission = resultObj.deniedAlways[i];
                                console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
                                result = -1
                            }
                        },
                        function(error) {
                            console.log('申请权限错误:' + error.code + " = " + error.message);
                        }
                    );
                }
            },
            onReady() {
                setTimeout((res) => {
                    this.init2();
                }, 500);
                this.onScanForResult();
            },
            methods: {
                init(scanLine) {
                    /**
                     * scanTypes - 扫码类型 不传或为null的话,支持所有
                     * AZTEC CODABAR CODE_39 CODE_93 CODE_128 DATA_MATRIX EAN_8 EAN_13 ITF PDF_417 QR_CODE UPC_A UPC_E
                     * */
                    var dic = {
                        //"scanTypes": ["CODE_128", "CODE_39", "QR_CODE"],
                        "isContinuouslyScan": true, //是否持续扫码
                        "scanLine": scanLine,
                        // "scanLine": { //扫码线,不配置,默认不显示
                        //  "filePath": plus.io.convertLocalFileSystemURL("../../static/ug_animation_img.png"),
                        //  "x": 0,
                        //  "y": 0,
                        //  "width": uni.getSystemInfoSync().screenWidth, //不配置,默认是组件的宽度
                        //  "toY": this.palyerHeight, //动画到y的位置,不配置,默认是组件的高度
                        //  "height": 30,
                        //  "animateDuration": 2,
                        //  "isAutoReverse": false, //true(上下来回移动) false(向下移动结束,从头开始)
                        // },
                        // "boundingBox": { //andorid识别区域
                        //  "left": 0,
                        //  "top": 0,
                        //  "right": uni.getSystemInfoSync().screenWidth,
                        //  "bottom": this.palyerHeight
                        // },
                        // "cutArea": { //ios识别区域
                        //  "x": 0,
                        //  "y": 0,
                        //  "width": uni.getSystemInfoSync().screenWidth,
                        //  "height": this.palyerHeight,
                        // }
                    }
                    console.log(JSON.stringify(dic))
                    this.$refs.hmsScan.init(dic, (res) => {
                        console.log("init:" + JSON.stringify(res));
                    })
                },
                init2() {
                    var scanLine = { //扫码线,不配置,默认不显示
                        "filePath": plus.io.convertLocalFileSystemURL("../../static/scanLine.png"),
                        "x": 0,
                        "y": 0,
                        "width": uni.getSystemInfoSync().screenWidth, //不配置,默认是组件的宽度
                        "toY": this.palyerHeight, //动画到y的位置,不配置,默认是组件的高度
                        "height": 30,
                        "animateDuration": 2,
                        "isAutoReverse": false, //true(上下来回移动) false(向下移动结束,从头开始)
                    }
                    this.init(scanLine);
                },
                init3() {
                    var scanLine = { //扫码线,不配置,默认不显示
                        "filePath": plus.io.convertLocalFileSystemURL("../../static/scanLine2.png"),
                        "x": 100,
                        "y": 300,
                        "width": uni.getSystemInfoSync().screenWidth - 200, //不配置,默认是组件的宽度
                        "height": 30,
                        "toY": this.palyerHeight - 300, //动画到y的位置,不配置,默认是组件的高度
                        "height": 30,
                        "animateDuration": 1,
                        "isAutoReverse": true, //true(上下来回移动) false(向下移动结束,从头开始)
                    }
                    this.init(scanLine);
                },
                onScanForResult() {
                    //监听扫码结果
                    this.$refs.hmsScan.onScanForResult((res) => {
                        console.log("onScanForResult:" + JSON.stringify(res));
                        uni.showModal({
                            title: '提示',
                            content: JSON.stringify(res),
                            success: function(res) {
                                if (res.confirm) {
                                    console.log('用户点击确定');
                                } else if (res.cancel) {
                                    console.log('用户点击取消');
                                }
                            }
                        });
                        /**
                         * 返回json字段说明:
                         * andorid:{"result":{"scanResult":"https://itunes.apple.com/cn/app/hello-uni-app/id1417078253","scanType":"QR_CODE",
                         * "other":{"showResult":"https://itunes.apple.com/cn/app/hello-uni-app/id1417078253","cornerPoints":[{"y":183,"x":17},{"y":16,"x":17},{"y":16,"x":183},{"y":182,"x":183}],
                         * "parserDic":{"theme":"","sceneType":"URL","linkValue":"https://itunes.apple.com/cn/app/hello-uni-app/id1417078253"},"scanTypeForm":1006}}}
                         * 
                         * ios:{"result":{"scanResult":"https://itunes.apple.com/cn/app/hello-uni-app/id1417078253",
                         * "other":{"zoomValue":1,"formatValue":"QR_CODE","time":"4","sceneType":"WebSite",
                         * "ResultPoint":[{"posY":"845.546120","posX":"38.256096"},{"posY":"77.935369","posX":"38.222356"},{"posY":"77.850768","posX":"393.087168"},
                         * {"posY":"846.450417","posX":"392.724744"}],"rawBytes":["xxx"],"text":"https://itunes.apple.com/cn/app/hello-uni-app/id1417078253",
                         * "numBits":480,"parserDic":{"url":"https://itunes.apple.com/cn/app/hello-uni-app/id1417078253","sceneType":"WebSite"},
                         * "exposureAdjustmentValue":0},"scanType":"QR_CODE"}}
                         * 
                         * ios和andorid共同字段:
                         * scanResult - 扫码结果
                         * scanType - 码类型
                         * other - 其它,sdk返回的其它信息
                         * */
                    })
                },
                openFrontCamera() {
                    //需要换为后置摄像头,执行init方法即可
                    this.$refs.hmsScan.openFrontCamera()
                },
                pauseContinuouslyScan() {
                    this.$refs.hmsScan.pauseContinuouslyScan()
                },
                resumeContinuouslyScan() {
                    this.$refs.hmsScan.resumeContinuouslyScan()
                },
                getLightStatus() {
                    this.$refs.hmsScan.getLightStatus((res) => {
                        console.log("getLightStatus:" + JSON.stringify(res));
                    })
                },
                switchLight() {
                    this.$refs.hmsScan.switchLight((res) => {
                        console.log("switchLight:" + JSON.stringify(res));
                    })
                },
                backClick() {
                    uni.navigateBack();
                },
                albumClick() {
                    uni.chooseImage({
                        count: 1, //默认9
                        sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
                        sourceType: ['album'], //从相册选择
                        success: function(res) {
                            console.log(JSON.stringify(res.tempFilePaths));
                            var filePath = res.tempFilePaths[0].replace('file://', '')
                            var dic = {
                                //"scanTypes": ["CODE_128", "CODE_39", "QR_CODE"],
                                "filePath": filePath
                            }
                            KJHmsScan.decodeForImage(dic, (res) => {
                                console.log("decodeForImage:" + JSON.stringify(res));
                                uni.showModal({
                                    title: '提示',
                                    content: JSON.stringify(res),
                                    success: function(res) {
                                        if (res.confirm) {
                                            console.log('用户点击确定');
                                        } else if (res.cancel) {
                                            console.log('用户点击取消');
                                        }
                                    }
                                });
                            })
                        }
                    });
                },
                lightClick() {
                    this.isLightOn = !this.isLightOn;
                    this.switchLight();
                }
            }
        }
    </script>
    <style>
        .hmsScan {
            justify-content: center;
            align-items: center;
            background-color: black;
        }

        .head {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            height: 44px;
            padding-left: 16px;
            padding-right: 16px;
            display: flex;
            flex-wrap: wrap;
            flex-direction: row;
            align-items: center;
            justify-content: space-between;
        }

        .text {
            color: white;
        }

        .back {
            width: 50rpx;
            height: 50rpx;
        }

        .album {
            width: 60rpx;
            height: 60rpx;
        }

        .light {
            position: absolute;
            top: 100px;
            left: 0;
            right: 0;
            display: flex;
            flex-wrap: wrap;
            flex-direction: column;
            align-items: center;
            justify-content: center;
        }

        .light_image {
            width: 60rpx;
            height: 120rpx;
        }

        .light>.text {
            font-size: 14px;
            margin-top: 8px;
        }

        .btns {
            position: fixed;
            bottom: 0;
            left: 0;
            display: flex;
            flex-wrap: wrap;
            flex-direction: column;
            align-items: flex-start;
            justify-content: center;
        }

        .btn {
            font-size: 10px !important;
        }
    </style>

隐私、权限声明

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

相机权限

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

插件使用的 华为统一扫码 SDK会采集数据,详情可参考:https://developer.huawei.com/consumer/cn/hms/huawei-scankit

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

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问