华为HMS Scan Kit扫码功能:一、Customized View Mode

Scan Kit提供4种调用方式,您可以根据需求选择相应的调用方式构建扫码功能。

  • 对于希望快速构建强大扫码功能的开发者,建议选择Default View Mode或者Customized View Mode。在这两种模式下,Scan Kit直接控制相机实现最优的相机Zoom控制、自适应的曝光调节、自适应对焦调节等操作,保障最佳的扫码体验,减少开发者的工作量。Default View Mode和Customized View Mode的区别在于后者支持开发者自定义扫码界面UI。

  • Bitmap Mode为开发者提供了充分的灵活性,对于希望完全自定义扫码流程并自行控制相机的开发者,可以选择Bitmap Mode构建您的扫码功能。当用户在扫描较小或者较远的二维码时,Scan Kit会返回需要放大的倍数给您的应用,您只需按照返回值调整相机焦距就能快速获取满足条件的图片。请注意,Scan Kit返回的放大倍数是通过检测结果和用户场景计算得出,建议您不要更改此放大倍数,否则可能会降低实际使用效果。

调用方式

扫码流程

扫码界面

功能

Default View Mode

Scan Kit处理

Scan Kit提供

相机扫码,导入图片扫码

Customized View Mode

Scan Kit处理

开发者自定义

相机扫码(可以叠加Bitmap mode增加导入图片扫码功能)

Bitmap Mode

开发者应用处理

开发者自定义

相机扫码、导入图片扫码

MultiProcessor Mode

开发者应用处理

开发者自定义

相机扫码、导入图片扫码;支持同时检测多个码,或者与ML Kit匹配实现同时识别码和人脸等其他对象

一、本篇主要实现Customized View Mode扫码

Customized View支持开发者自定义扫码界面,扫码过程和相机控制将由Scan Kit完成。

1、 业务流程

使用Customized View Mode的主要业务流程如下:

1. 用户打开应用发起扫码请求。

2. 校验是否有相机权限和文件读取权限。

3. 初始化应用定制的view,构建扫码界面,开始扫码。

4. 如果扫码成功,HMS SDK回调应用的“onResult”接口传递扫码结果。

5. 应用封装扫码结果返回给用户。

 

扫码速度很快,实现的效果图如下:

Scan Kit支持十多种码制式

Scan Kit支持扫描13种全球主流的码制式

已支持的码制式:

  • 一维码:EAN-8、EAN-13、UPC-A、UPC-E、Codabar、Code 39、Code 93、Code 128、ITF

  • 二维码:QR Code、Data Matrix、PDF417、Aztec            

码制式

int值

Code 128

HmsScan.CODE128_SCAN_TYPE

Code 39

HmsScan.CODE39_SCAN_TYPE

Code 93

HmsScan.CODE93_SCAN_TYPE

Codabar

HmsScan.CODABAR_SCAN_TYPE

EAN-13

HmsScan.EAN13_SCAN_TYPE

EAN-8

HmsScan.EAN8_SCAN_TYPE

ITF

HmsScan. ITF14_SCAN_TYPE

UPC-A

HmsScan.UPCCODE_A_SCAN_TYPE

UPC-E

HmsScan.UPCCODE_E_SCAN_TYPE

QR code

HmsScan.QRCODE_SCAN_TYPE

PDF417

HmsScan. PDF417_SCAN_TYPE

Aztec

HmsScan. AZTEC_SCAN_TYPE

Data Matrix

HmsScan. DATAMATRIX_SCAN_TYPE

2、Android Studio环境开发流程:

2.1 相关配置如下:

1、创建HuaweiScan应用;

2、 配置HMS SDK的maven仓地址。

    a. 打开AndroidStudio项目级build.gradle文件。

    b. 在allprojects ->repositories里面配置HMS SDK的maven仓地址。

         maven {url 'http://developer.huawei.com/repo/'}

    c. 在buildscript->repositories里面配置HMS SDK的maven仓地址。

         maven {url 'http://developer.huawei.com/repo/'}

    d.  在buildscript ->dependencies里面增加配置。

         classpath 'com.huawei.agconnect:agcp:1.2.1.301'

     b. 引用SDK,Scan Kit提供两种SDK,您可以根据需求选择合适的SDK。


3、 添加编译依赖。

 a. 打开应用级的build.gradle文件。

      

 

 b. 引用SDK,Scan Kit提供两种SDK,您可以根据需求选择合适的SDK。

 

SDK

Scan Kit SDK-Plus

Scan Kit SDK

API及功能特性

相同

相同

识别能力

华为手机

Excellent(使用HMS Core内的增强识别模型)

Excellent(使用HMS Core内的增强识别模型)

非华为手机

Excellent(SDK自带的增强识别模型)

Good(SDK自带的普通识别模型)

SDK大小

≈3.3M

≈0.8M

适用开发者

对SDK大小不敏感且希望所有机型均具备最佳体验的开发者

对SDK大小敏感的开发者

坐标名称

com.huawei.hms:scanplus:{version}

com.huawei.hms:scan:{version}

如使用Scan Kit SDK,则在“dependencies”中添加如下编译依赖,{version} 需要替换为实际的SDK版本号,如当前版本:            implementation 'com.huawei.hms:scan:1.1.1.301'。

dependencies{ 
  implementation 'com.huawei.hms:scan:{version}' 
//    implementation 'com.huawei.hms:scanplus:1.1.1.301'
 }

c.  在文件头添加配置。

aply plugin: 'com.huawei.agconnect'

4、修改完build.gradle文件,点击“Sync Now”等待同步完成。

5、多语言设置。

−  如果您的应用不需要设置只支持某些特定语言,则请忽略本步骤。应用将默认支持所有HMS SDK支持的语言。

−  如果您的应用需要设置只支持某些特定语言,则可通过本步骤配置:

在“android”->“defaultConfig”中新增resConfigs配置,“en-rGB”(英式英语) 和 “zh-rCN”(简体中文) 为必须配置的语种,配置格式如下:

android { 
    defaultConfig{ 
        ... 
        resConfigs "en-rGB", "zh-rCN", "需要支持的其他语言" 
    } 
 }

HMS SDK支持的语言列表请参考 HMS SDK支持的语言

6、配置混淆脚本

如果开发者开启混淆配置,请按照如下步骤配置,避免HMS SDK相关代码被混淆导致功能异常。

1.  打开Android工程的混淆配置文件。

2.  加入排除HMS SDK的混淆配置。

-ignorewarnings 
-keepattributes *Annotation*  
-keepattributes Exceptions  
-keepattributes InnerClasses  
-keepattributes Signature  
-keepattributes SourceFile,LineNumberTable  
-keep class com.hianalytics.android.**{*;}  
-keep class com.huawei.**{*;}

  3. 如果开发者使用了AndResGuard,需要在混淆配置文件中加入AndResGuard白名单。

"R.string.hms*",           
"R.string.connect_server_fail_prompt_toast",           
"R.string.getting_message_fail_prompt_toast",            
"R.string.no_available_network_prompt_toast", 
"R.string.third_app_*",           
"R.string.upsdk_*",           
"R.layout.hms*",           
"R.layout.upsdk_*",           
"R.drawable.upsdk*",          
"R.color.upsdk*",       
"R.dimen.upsdk*",      
"R.style.upsdk*", 
"R.string.agc*"

2.2 添加所需权限

Scan Kit时,开发者需要先在Manifest文件中中指定相应的权限。构建相机扫码功能,需要申请“CAMERA”(相机权限);构建导入图片扫码功能,需要申请“READ_EXTERNAL_STORAGE”(读文件权限)。

<!--相机权限--> 
<uses-permission android:name="android.permission.CAMERA" /> 
<!--读文件权限--> 
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 
<!--使用特性--> 
<uses-feature android:name="android.hardware.camera" /> 
<uses-feature android:name="android.hardware.camera.autofocus" />

2.3 创建修改扫码页面的操作

在默认的 MainActivity.java文件中修改对应的布局文件(activity_main.xml):上面一个按钮,点击后跳转到扫码界面,识别成功返回在button按钮下面显示扫码的码内容。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn_sacning"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="华为Sacn kit扫码"
        android:textSize="18sp" />

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Hello World!"
        android:textSize="18sp" />

</LinearLayout>

 

  • 动态获取权限:
 btn_sacning.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //DEFINED_CODE为用户自定义用于接收权限校验结果
                ActivityCompat.requestPermissions(MainActivity.this,
                        new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE},
                        DEFINED_CODE);
            }
        });
  • 处理动态获取的权限结果:
    /**
     * 权限返回的结果处理
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (permissions == null || grantResults == null || grantResults.length < 2 || grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        if (requestCode == DEFINED_CODE) {
            //获得权限后,跳转到开始扫码界面
            this.startActivityForResult(new Intent(this, ScaningActivity.class), REQUEST_CODE_SCAN);
        }
    }

onActivityResult(...)对扫码返回的结果进行处理:

  @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        //接收返回的扫码结果
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != RESULT_OK || data == null) {
            return;
        }
        if (requestCode == REQUEST_CODE_SCAN) {
            HmsScan hmsScan = data.getParcelableExtra(ScaningActivity.SCAN_RESULT);
            //自定义扫码界面返回的结果
            if (hmsScan != null && !TextUtils.isEmpty(hmsScan.getOriginalValue())) {
//                Toast.makeText(MainActivity.this, hmsScan.getOriginalValue(), Toast.LENGTH_SHORT).show();
                if (tv_result != null) {
                    tv_result.setText(hmsScan.getOriginalValue());
                }
            }
        }

    }

完整的MainActivity 代码如下:

public class MainActivity extends AppCompatActivity {
    public static final int DEFINED_CODE = 222;//请求权限的code值
    private static final int REQUEST_CODE_SCAN = 0X01;//请求带返回结果的跳转code值
     Button btn_sacning;
    TextView tv_result;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_sacning = (Button) findViewById(R.id.btn_sacning);
        tv_result = (TextView) findViewById(R.id.tv_result);
        btn_sacning.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //DEFINED_CODE为用户自定义用于接收权限校验结果
                ActivityCompat.requestPermissions(MainActivity.this,
                        new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE},
                        DEFINED_CODE);
            }
        });
    }

    /**
     * 权限返回的结果处理
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (permissions == null || grantResults == null || grantResults.length < 2 || grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        if (requestCode == DEFINED_CODE) {
            //获得权限后,跳转到开始扫码界面
            this.startActivityForResult(new Intent(this, ScaningActivity.class), REQUEST_CODE_SCAN);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        //接收返回的扫码结果
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != RESULT_OK || data == null) {
            return;
        }
        if (requestCode == REQUEST_CODE_SCAN) {
            HmsScan hmsScan = data.getParcelableExtra(ScaningActivity.SCAN_RESULT);
            if (hmsScan != null && !TextUtils.isEmpty(hmsScan.getOriginalValue())) {
                //Toast.makeText(MainActivity.this, hmsScan.getOriginalValue(), Toast.LENGTH_SHORT).show();
                if (tv_result != null) {
                    //显示扫码回来的内容
                    tv_result.setText(hmsScan.getOriginalValue());
                }
            }
        }
    }
}

 

扫码页面ScaningActivity.java 的处理:ScaningActivity.java对应的布局文件activity_scaning.xml (扫码布局页面可自定义样式)

<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:my_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- customize layout needed by scankit for camera preview -->
    <FrameLayout
        android:id="@+id/rim"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#C0C0C0"></FrameLayout>


    <!--  自定义返回按钮 -->
    <ImageView
        android:id="@+id/back_img"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:layout_alignParentStart="true"
        android:layout_marginStart="12dp"
        android:layout_marginTop="4dp"
        android:gravity="center"
        android:padding="12dp"
        android:src="@drawable/back" />

    <!--  customize scanning mask  -->
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:layout_centerHorizontal="true"
        android:alpha="0.1"
        android:background="#FF000000" />

    <!--  customize scanning viewfinder  -->
    <ImageView
        android:id="@+id/scan_view_finder"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_centerInParent="true"
        android:layout_centerHorizontal="true"
        android:background="@drawable/scanningframe" />

</RelativeLayout>

设置scan_view_finder的背景样式;

<?xml version="1.0" encoding="utf-8"?><!-- 设置扫码框样式 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <!-- 设置边框的宽度和颜色 -->
    <stroke
        android:width="3dp"
        android:color="#e1ffff" />
    <!-- 设置框内的填充色  -->
    <solid android:color="#1f00BCD4" />
    <!-- 设置圆角 -->
    <corners android:radius="5dip" />
    <!-- 设置内边距 -->
    <padding
        android:bottom="2dp"
        android:left="2dp"
        android:right="2dp"
        android:top="2dp" />
</shape>

自定义布局的整体操作可参照官方Demo ,只需修改扫码的UI界面,再修改对应的代码。


import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.Window;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.huawei.hms.hmsscankit.OnResultCallback;
import com.huawei.hms.hmsscankit.RemoteView;
import com.huawei.hms.ml.scan.HmsScan;

public class ScaningActivity extends Activity {

    //声明 RemoteView instance
    private RemoteView remoteView;
    //声明 key,用于从scankit得到返回的值
    public static final String SCAN_RESULT = "scanResult";

    int mSceenWidth;
    int mSceenHeight;
    //scan_view_finder width & height is  300dp
    final int SCAN_FRAME_SIZE = 300;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_scaning);


        //1.设置扫码识别区域,您可以按照需求调整参数
        DisplayMetrics dm = getResources().getDisplayMetrics();
        float density = dm.density;
        //2.获取屏幕尺寸
        mSceenWidth = getResources().getDisplayMetrics().widthPixels;
        mSceenHeight = getResources().getDisplayMetrics().heightPixels;

        int scanFrameSize = (int) (SCAN_FRAME_SIZE * density);

        //3.声明 viewfinder'的 矩形,在布局中间
        //设置扫描区域(可选,矩形可以为空,如果不配置,默认是中心的布局)
        Rect rect = new Rect();
        rect.left = mSceenWidth / 2 - scanFrameSize / 2;
        rect.right = mSceenWidth / 2 + scanFrameSize / 2;
        rect.top = mSceenHeight / 2 - scanFrameSize / 2;
        rect.bottom = mSceenHeight / 2 + scanFrameSize / 2;


        //初始化RemoteView,并通过如下方法设置参数:
        // setContext()(必选)传入context、setBoundingBox()设置扫描区域、
        // setFormat()设置识别码制式,设置完毕调用build()方法完成创建
        remoteView = new RemoteView.Builder().setContext(this).setBoundingBox(rect).setFormat(HmsScan.ALL_SCAN_TYPE).build();
        //将自定义view加载到activity
        remoteView.onCreate(savedInstanceState);
        remoteView.setOnResultCallback(new OnResultCallback() {
            @Override
            public void onResult(HmsScan[] result) {
                //获取到扫码结果HmsScan,判断结果是否有效
                if (result != null && result.length > 0 && result[0] != null && !TextUtils.isEmpty(result[0].getOriginalValue())) {
                    Intent intent = new Intent();
                    intent.putExtra(SCAN_RESULT, result[0]);
                    setResult(RESULT_OK, intent);
                    ScaningActivity.this.finish();
                }
            }
        });

        //添加 remoteView 到Framelayout布局中
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
        //绑定相机预览布局
        FrameLayout frameLayout = findViewById(R.id.rim);
        frameLayout.addView(remoteView, params);

        //设置返回监听
        ImageView backBtn = findViewById(R.id.back_img);
        backBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ScaningActivity.this.finish();
            }
        });
    }

    //管理 remoteView 生命周期
    @Override
    protected void onStart() {
        super.onStart();
        remoteView.onStart();
    }

    @Override
    protected void onResume() {
        super.onResume();
        remoteView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        remoteView.onPause();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        remoteView.onDestroy();
    }

    @Override
    protected void onStop() {
        super.onStop();
        remoteView.onStop();
    }

}

不想使用自定义页面 更简单,可参照下一篇:

华为Scan Kit扫码服务功能:二、Default View Mode

 

更详细的细节描述请参考:

华为官方使用指南

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值