Android开发笔记(一百八十三)利用HMS轻松扫描二维码

Posted aqi00

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android开发笔记(一百八十三)利用HMS轻松扫描二维码相关的知识,希望对你有一定的参考价值。

开源的android系统实际上只提供基本的系统服务,不提供常见的扩展服务诸如地图、邮箱、搜索、推送、机器学习、应用内支付等,这些扩展服务被谷歌公司打包成GMS套件(全称Google Mobile Service,中文名叫谷歌移动服务)。在海外市场,许多商用App都依赖于GMS提供的服务,手机缺少GMS会使得这些App没法使用,而手机厂商预装GMS套件需要获得谷歌公司授权。2019年华为公司遭到美国制裁,导致华为手机没能获得GMS授权,致使海外市场陷入寒冬。为此,华为公司推出了自主可控的HMS套件(全称Huawei Mobile Service,中文名叫华为移动服务),意图打破制裁。
HMS是华为公司提供的一套App扩展服务框架,它分为两部分,一部分是面向普通用户的预装App,包括花瓣地图、花瓣邮箱、花瓣搜索、花瓣支付等;另一部分是面向开发者的HMS Core,它给开发者提供API接口,用于在App开发时集成相关服务。HMS Core是华为移动服务提供的端、云开放能力的合集,包含华为账号、应用内支付、推送服务、游戏服务、定位服务、地图服务、广告服务和机器学习服务等,它的开源代码仓库地址为https://gitee.com/hms-core,开发者可在该仓库下载对应源码学习。
扫描二维码是HMS的一项基础服务,虽然谷歌公司也提供了zxing扫码框架,但是zxing框架的集成步骤不够简洁,而且它的识别速度偏慢,识别准确率也不高,远不如HMS的扫码服务来得好用。下面介绍如何在App工程中集成HMS的扫码服务。
首先,因为扫码属于第三方服务,所以要修改模块的build.gradle,往dependencies节点添加如下一行配置,表示导入指定版本的扫码库:

implementation 'com.huawei.hms:scanplus:1.3.1.300'

接着打开AndroidManifest.xml,补充以下的相机权限配置

<!-- 相机 -->
<uses-permission android:name="android.permission.CAMERA" />

然后在Java代码中增加用于扫码的远程视图,并指定扫码结果的回调事件,新增的代码片段如下所示:

private RemoteView remoteView; // 声明一个HMS的远程视图对象
private int SCAN_FRAME_SIZE = 240; // 扫码框的默认尺寸

// 添加扫码的远程视图
private void addRemoteView(Bundle savedInstanceState) 
    int screenWidth = Utils.getScreenWidth(this); // 获取屏幕宽度
    int screenHeight = Utils.getScreenHeight(this); // 获取屏幕高度
    int scanFrameSize = (int) (SCAN_FRAME_SIZE * Utils.getScreenDensity(this));
    // 计算取景器的四周边缘。如果没有指定设置,它将位于布局的中间位置。
    Rect rect = new Rect();
    rect.left = screenWidth / 2 - scanFrameSize / 2;
    rect.right = screenWidth / 2 + scanFrameSize / 2;
    rect.top = screenHeight / 2 - scanFrameSize / 2;
    rect.bottom = screenHeight / 2 + scanFrameSize / 2;
    // 初始化远程视图实例
    remoteView = new RemoteView.Builder().setContext(this)
            .setBoundingBox(rect).setFormat(HmsScan.ALL_SCAN_TYPE).build();
    // 当光线昏暗时,展示闪光灯开关按钮,以便用户决定是否开灯
    remoteView.setOnLightVisibleCallback(visible -> 
        if (visible) 
            iv_flash.setVisibility(View.VISIBLE);
        
    );
    // 设置扫描结果的回调事件
    remoteView.setOnResultCallback(result -> showResult(result));
    // 将自定义视图加载到活动中.
    remoteView.onCreate(savedInstanceState);
    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
    rl_scan.addView(remoteView, params); // 往相对布局添加远程视图


// 显示扫码识别结果
private void showResult(HmsScan[] result) 
    if (result != null && result.length > 0 && result[0] != null &&
            !TextUtils.isEmpty(result[0].getOriginalValue())) 
        Intent intent = new Intent(this, ScanResultActivity.class);
        intent.putExtra(ScanUtil.RESULT, result[0]);
        startActivity(intent); // 跳转到扫码结果页
    

在扫码结果页面,HMS不但支持获取结果文本,还支持获取条码的编码格式与结果类型,从而允许开发者更精准地辨别条码归属。下面是具体的扫码结果解析代码:

// 解析扫码结果
private void parserScanResult() 
    // 从意图中获取可折叠的扫码结果
    HmsScan hmsScan = getIntent().getParcelableExtra(ScanUtil.RESULT);
    try 
        String desc = String.format("扫码结果如下:\\n\\t\\t格式为%s\\n\\t\\t类型为%s\\n\\t\\t内容为%s",
                getCodeFormat(hmsScan.getScanType()),
                getResultType(hmsScan.getScanType(), hmsScan.getScanTypeForm()),
                hmsScan.getOriginalValue());
        tv_result.setText(desc);
     catch (Exception e) 
        e.printStackTrace();
    


// 获取扫码格式
private String getCodeFormat(int scan_type) 
    String codeFormat = "未知(Unknown)";
    if (scan_type == HmsScan.QRCODE_SCAN_TYPE) 
        codeFormat = "快速响应码(QR code)";
     else if (scan_type == HmsScan.AZTEC_SCAN_TYPE) 
        codeFormat = "阿兹特克码(AZTEC code)";
     else if (scan_type == HmsScan.DATAMATRIX_SCAN_TYPE) 
        codeFormat = "数据矩阵码(DATAMATRIX code)";
     else if (scan_type == HmsScan.PDF417_SCAN_TYPE) 
        codeFormat = "便携数据文件码(PDF417 code)";
     else if (scan_type == HmsScan.EAN13_SCAN_TYPE) 
        codeFormat = "欧洲商品编码-标准版(EAN13 code)";
     else if (scan_type == HmsScan.EAN8_SCAN_TYPE) 
        codeFormat = "欧洲商品编码-缩短版(EAN8 code)";
     else if (scan_type == HmsScan.ITF14_SCAN_TYPE) 
        codeFormat = "外箱条码(ITF14 code)";
     else if (scan_type == HmsScan.UPCCODE_A_SCAN_TYPE) 
        codeFormat = "商品统一代码-通用(UPCCODE_A)";
     else if (scan_type == HmsScan.UPCCODE_E_SCAN_TYPE) 
        codeFormat = "商品统一代码-短码(UPCCODE_E)";
     else if (scan_type == HmsScan.CODABAR_SCAN_TYPE) 
        codeFormat = "库德巴码(CODABAR)";
    
    return codeFormat;


// 获取结果类型
private String getResultType(int scan_type, int scanForm) 
    String resultType = "文本(Text)";
    if (scan_type == HmsScan.QRCODE_SCAN_TYPE) 
        if (scanForm == HmsScan.PURE_TEXT_FORM) 
            resultType = "文本(Text)";
         else if (scanForm == HmsScan.URL_FORM) 
            resultType = "网址(WebSite)";
         // 此处省略若干格式判断
     else if (scan_type == HmsScan.EAN13_SCAN_TYPE) 
        if (scanForm == HmsScan.ISBN_NUMBER_FORM) 
            resultType = "国际标准书号(ISBN)";
         else if (scanForm == HmsScan.ARTICLE_NUMBER_FORM) 
            resultType = "产品(Product)";
        
     else if (scan_type == HmsScan.EAN8_SCAN_TYPE
            || scan_type == HmsScan.UPCCODE_A_SCAN_TYPE
            || scan_type == HmsScan.UPCCODE_E_SCAN_TYPE) 
        if (scanForm == HmsScan.ARTICLE_NUMBER_FORM) 
            resultType = "产品(Product)";
        
    
    return resultType;

接下来分别举个条形码例子与二维码例子,看看到底能扫出什么东西,条形码例子如下图所示,这是某个商品的条形码。

 

 二维码例子如下图所示,这是清华大学的微信公众号二维码。

 运行测试App,打开扫码界面如下图所示。

 把扫码框对准条形码图片,App识别成功跳到结果页面如下图所示。

 返回之后继续扫描二维码图片,App识别成功跳到结果页面如下图所示。

由此验证了HMS扫码服务的准确性和高效率。你还等什么呢?快来试试HMS的扫码服务吧,完整的范例源码见https://gitee.com/hms-core/hms-scan-demo。


点此查看Android开发笔记的完整目录

以上是关于Android开发笔记(一百八十三)利用HMS轻松扫描二维码的主要内容,如果未能解决你的问题,请参考以下文章

Android开发笔记(一百八十四)利用TBS浏览各种文档

Android开发笔记(一百八十四)利用TBS浏览各种文档

Android开发笔记(一百八十四)利用TBS浏览各种文档

Android开发笔记(一百八十九)利用LAME录制MP3音频

Android开发笔记(一百八十九)利用LAME录制MP3音频

Android开发笔记(一百八十九)利用LAME录制MP3音频