栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

安卓集成华为HMS Scankit实现自定义扫码功能

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

安卓集成华为HMS Scankit实现自定义扫码功能

实现扫码功能

使用的是集成华为扫描的SDK,UI界面借鉴的是谷歌官方的Zxing项目中的自定义view,两者结合实现。

先上效果图:

  1. 先在项目根级别(build.gradle)当中配置HMS Core SDK的Maven仓地址。
// 配置HMS Core SDK的Maven仓地址。
maven {url 'https://developer.huawei.com/repo/'}`



2. 在对应module的build.gradle(Module:app)中添加依赖

dependencies {
    implementation 'com.huawei.hms:scanplus:1.3.2.300'
}
  1. 在清单文件里面添加静态权限
 
     
    

    

    
    
  1. 还需要在代码中申请相机的动态权限
public static final int DEFINED_CODE = 222;
public static final int DECODE = 1;

//跳转到扫描界面的监听中调用
 requestPermission(DEFINED_CODE, DECODE);

 private void requestPermission(int requestCode, int mode) {
        ActivityCompat.requestPermissions(
                this,
                new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE},
                requestCode);
    }
    
 @Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
      if (permissions == null || grantResults == null) {
            return;
        }
      if (grantResults.length < 2 || grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) {
            return;
        }
 
      //Customized View Mode  使用的是自定义扫码界面  所以这块权限请求成功后才跳转到扫码界面
      if (requestCode == DEFINED_CODE) {
            Intent intent = new Intent(this, CustomizedViewActivity.class);
            this.startActivityForResult(intent, REQUEST_CODE_DEFINE);
        }
    }


//此处是扫描界面处理完成的扫描结果回调
 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != RESULT_OK || data == null) {
            return;
        }
  
      //Customized View
     if (requestCode == REQUEST_CODE_DEFINE) {
        HmsScan obj = data.getParcelableExtra(CustomizedViewActivity.SCAN_RESULT);
        if (obj != null) {
        //拿到扫描信息根据自己需求自行处理 
            Toast.makeText(this, obj.toString(), Toast.LENGTH_SHORT).show();
        }
    }
    }

5.**扫描界面 **
xml显示:


    
    
    

        

        

    


activity当中处理

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Bundle;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.widget.frameLayout;
import android.widget.LinearLayout;

import com.example.jianzhuapplication.R;
import com.huawei.hms.hmsscankit.OnResultCallback;
import com.huawei.hms.hmsscankit.RemoteView;
import com.huawei.hms.hmsscankit.ScanUtil;
import com.huawei.hms.ml.scan.HmsScan;
import com.huawei.hms.ml.scan.HmsScanAnalyzerOptions;

import java.io.IOException;

import androidx.appcompat.app.AppCompatActivity;

public class CustomizedViewActivity extends AppCompatActivity {

    private frameLayout rim;
    private int mScreenWidth;
    private int mScreenHeight;
    //The width and height of scan_view_finder is both 240 dp.
    final int SCAN_frame_SIZE = 240;
    private RemoteView remoteView;//Declare the key. It is used to obtain the value returned from Scan Kit.
    public static final String SCAN_RESULT = "scanResult";
    public static final int REQUEST_CODE_PHOTO = 0x1113;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_customized_view);

        rim = (frameLayout) findViewById(R.id.rim);
        //1. Obtain the screen density to calculate the viewfinder's rectangle.
        DisplayMetrics dm = getResources().getDisplayMetrics();
        float density = dm.density;
        //2. Obtain the screen size.
        mScreenWidth = getResources().getDisplayMetrics().widthPixels;
        mScreenHeight = getResources().getDisplayMetrics().heightPixels;

        int scanframeSize = (int) (SCAN_frame_SIZE * density);

        //3. Calculate the viewfinder's rectangle, which in the middle of the layout.
        //Set the scanning area. (Optional. Rect can be null. If no settings are specified, it will be located in the middle of the layout.)
        Rect rect = new Rect();
        rect.left = mScreenWidth / 2 - scanframeSize / 2;
        rect.right = mScreenWidth / 2 + scanframeSize / 2;
        rect.top = mScreenHeight / 2 - scanframeSize / 2;
        rect.bottom = mScreenHeight / 2 + scanframeSize / 2;


        //Initialize the RemoteView instance, and set callback for the scanning result.
        remoteView = new RemoteView.Builder().setContext(this).setBoundingBox(rect).setFormat(HmsScan.ALL_SCAN_TYPE).build();
        // Subscribe to the scanning result callback event.
        remoteView.setonResultCallback(new onResultCallback() {
            @Override
            public void onResult(HmsScan[] result) {
                //Check the result.
                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);
                    CustomizedViewActivity.this.finish();
                }
            }
        });

        // Load the customized view to the activity.
        remoteView.onCreate(savedInstanceState);
        frameLayout.LayoutParams params = new frameLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
        rim.addView(remoteView, params);
    }

    @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();
    }

    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK && requestCode == REQUEST_CODE_PHOTO) {
            try {
                Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), data.getData());
                HmsScan[] hmsScans = ScanUtil.decodeWithBitmap(CustomizedViewActivity.this, bitmap, new HmsScanAnalyzerOptions.Creator().setPhotoMode(true).create());
                if (hmsScans != null && hmsScans.length > 0 && hmsScans[0] != null && !TextUtils.isEmpty(hmsScans[0].getOriginalValue())) {
                    Intent intent = new Intent();
                    intent.putExtra(SCAN_RESULT, hmsScans[0]);
                    setResult(RESULT_OK, intent);
                    CustomizedViewActivity.this.finish();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

自定义view ---->ViewfinderView.java
使用的是XZing当中的view效果

package com.iqos.qrscanner.widget;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;

import com.iqos.qrscanner.R;
import com.iqos.qrscanner.utils.BitmapUtil;

public final class ViewfinderView extends View {
    private static final long ANIMATION_DELAY = 1L;//刷新界面的时间
    private static final int DEFAULT_CORNER_WIDTH = 1;//四个绿色边角对应的宽度
    private static final int DEFAULT_CORNER_LENGTH = 30;//四个绿色边角对应的长度
    private static final int DEFAULT_MOVE_SPEED = 5;//中间那条线每次刷新移动的距离
    private static final int DEFAULT_TIP_TEXT_SIZE = 14;//默认字体大小
    private static final int DEFAULT_SCAN_RES_RECT_WIDTH = 18;//扫描线的粗细
    private static final int DEFAULT_TXT_PADDING_RECT = 10;//文本与取景框间距(默认值)
    private Paint mPaint = new Paint();//画笔对象的引用
    private int slideTop;//中间滑动线的最顶端位置
    private boolean tipAboveRect;//文本在上?
    private boolean isFirst;
    private int tipTextSize;//扫码文本字体大小
    private int scanLineColor;//扫描的线的颜色
    private int cornerColor;//角的颜色
    private int cornerWidth;//角的宽度
    private int cornerLength;//角的长
    private int textPaddingRect;//文本与取景框间距
    private int scanLineRes;//扫描线的资源id
    private int lineMoveSpeed;//扫描线移动速度
    private String tipText;//显示文本
    private String scanViewTitle;//扫码界面的Title
    private Context context;
    private static final String TAG = "ViewfinderView";
    private Point screenResolution;
    private Rect framingRect;

    
    public ViewfinderView(Context context, AttributeSet attrs) {
        super(context, attrs);
        Log.e(TAG, "ViewfinderView: 进入:  " );
        this.context = context;
        this.initialAttrs(attrs);
    }

    
    private void initialAttrs(AttributeSet attrs) {
        TypedArray td = context.obtainStyledAttributes(attrs, R.styleable.ViewfinderView);

        //----------------------------------提示文本--------------------------------------------
        tipText = td.getString(R.styleable.ViewfinderView_scan_tip_text);

        //----------------------------------文本是否处于扫描框的上方--------------------------------
        tipAboveRect = td.getBoolean(R.styleable.ViewfinderView_scan_text_above_rect, false);

        //----------------------------------提示文本与扫描框的距离---------------------------------
        textPaddingRect = td.getDimensionPixelSize(R.styleable.ViewfinderView_scan_text_padding_rect, DEFAULT_TXT_PADDING_RECT);

        //----------------------------------提示文本大小---------------------------------------
        tipTextSize = td.getDimensionPixelSize(R.styleable.ViewfinderView_scan_tip_text_size, DEFAULT_TIP_TEXT_SIZE);

        //----------------------------------角的长度---------------------------------------------
        cornerLength = td.getDimensionPixelSize(R.styleable.ViewfinderView_scan_rect_corner_length, DEFAULT_CORNER_LENGTH);

        //----------------------------------角的颜色---------------------------------------------
        cornerColor = td.getColor(R.styleable.ViewfinderView_scan_rect_corner_color, Color.GREEN);

        //----------------------------------扫描的线的颜色---------------------------------------------
        scanLineColor = td.getColor(R.styleable.ViewfinderView_scan_rect_corner_color, Color.GREEN);

        //----------------------------------角宽-----------------------------------------------
        cornerWidth = td.getDimensionPixelOffset(R.styleable.ViewfinderView_scan_rect_corner_width, DEFAULT_CORNER_WIDTH);

        //----------------------------------扫描线---------------------------------------------
        scanLineRes = td.getResourceId(R.styleable.ViewfinderView_scan_line_res, -1);

        //----------------------------------扫描界面的Title---------------------------------------------
        scanViewTitle = td.getString(R.styleable.ViewfinderView_scan_view_title_text);

        //----------------------------------扫描线移动速度--------------------------------------
        lineMoveSpeed = td.getInteger(R.styleable.ViewfinderView_scan_line_move_speed, DEFAULT_MOVE_SPEED);
        lineMoveSpeed = lineMoveSpeed > DEFAULT_MOVE_SPEED ? DEFAULT_MOVE_SPEED : lineMoveSpeed;

        td.recycle();
    }

    
    @SuppressLint("DrawAllocation")
    @Override
    public void onDraw(Canvas canvas) {
       
        DisplayMetrics dm = context.getResources().getDisplayMetrics();
        int screenWidth = dm.widthPixels;
        int screenHeight = dm.heightPixels;
        screenResolution = new Point(screenWidth, screenHeight);
        int mWidth = screenResolution.x * 2 / 3;
        int mHeight = screenResolution.x * 2 / 3;
        int leftOffset = (screenResolution.x - mWidth) >> 1;
        int topOffset = (screenResolution.y - mHeight) >> 2;
        framingRect = new Rect(leftOffset, topOffset, leftOffset + mWidth, topOffset + mHeight);
        //初始化中间线滑动的最上边和最下边
        if (!isFirst) {
            isFirst = true;
            slideTop = framingRect.top;
        }
        //获取屏幕的宽和高
        int width = getWidth();
        int height = getHeight();
        //画出扫描框外面的阴影部分,共四个部分,扫描框的上面到屏幕上面,扫描框的下面到屏幕下面
        //扫描框的左边面到屏幕左边,扫描框的右边到屏幕右边
        mPaint.setAlpha(0x40);
        canvas.drawRect(0, 0, width, framingRect.top, mPaint);
        canvas.drawRect(0, framingRect.top, framingRect.left, framingRect.bottom + 1, mPaint);
        canvas.drawRect(framingRect.right + 1, framingRect.top, width, framingRect.bottom + 1, mPaint);
        canvas.drawRect(0, framingRect.bottom + 1, width, height, mPaint);
        //画扫描框边上的角,总共8个部分
        mPaint.setAlpha(0xff);
        mPaint.setColor(cornerColor);
        canvas.drawRect(framingRect.left, framingRect.top, framingRect.left + cornerLength, framingRect.top + cornerWidth, mPaint);
        canvas.drawRect(framingRect.left, framingRect.top, framingRect.left + cornerWidth, framingRect.top + cornerLength, mPaint);
        canvas.drawRect(framingRect.right - cornerLength, framingRect.top, framingRect.right, framingRect.top + cornerWidth, mPaint);
        canvas.drawRect(framingRect.right - cornerWidth, framingRect.top, framingRect.right, framingRect.top + cornerLength, mPaint);
        canvas.drawRect(framingRect.left, framingRect.bottom - cornerWidth, framingRect.left + cornerLength, framingRect.bottom, mPaint);
        canvas.drawRect(framingRect.left, framingRect.bottom - cornerLength, framingRect.left + cornerWidth, framingRect.bottom, mPaint);
        canvas.drawRect(framingRect.right - cornerLength, framingRect.bottom - cornerWidth, framingRect.right, framingRect.bottom, mPaint);
        canvas.drawRect(framingRect.right - cornerWidth, framingRect.bottom - cornerLength, framingRect.right, framingRect.bottom, mPaint);
        //---------------绘制中间的线,每次刷新界面,中间的线往下移动SPEED_DISTANCE---------------//
        slideTop += lineMoveSpeed;
        if (slideTop + DEFAULT_SCAN_RES_RECT_WIDTH >= framingRect.bottom) {
            slideTop = framingRect.top;
        }
        Rect lineRect = new Rect();
        lineRect.left = framingRect.left;
        lineRect.right = framingRect.right;
        lineRect.top = slideTop;
        lineRect.bottom = slideTop + DEFAULT_SCAN_RES_RECT_WIDTH;
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), scanLineRes);
        if (null == bitmap) {
            bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.qr_code_scan_line);
            bitmap = BitmapUtil.tintBitmap(bitmap, scanLineColor);
        }
        canvas.drawBitmap(bitmap, null, lineRect, mPaint);
        //----------------------------画扫描框下面的字---------------------------------//
        mPaint.setColor(Color.WHITE);
        mPaint.setTextSize(tipTextSize);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setTypeface(Typeface.create(ViewfinderView.class.getSimpleName(), Typeface.BOLD));
        if (!TextUtils.isEmpty(tipText)) {
            if (tipAboveRect) {
                canvas.drawText(tipText, getWidth() >> 1, framingRect.top - textPaddingRect, mPaint);
            } else {
                Rect rect = new Rect();
                mPaint.getTextBounds(tipText, 0, tipText.length(), rect);
                canvas.drawText(tipText, getWidth() >> 1, framingRect.bottom + rect.height() + textPaddingRect, mPaint);
            }
        }
        //只刷新扫描框的内容,其他地方不刷新
        postInvalidateDelayed(ANIMATION_DELAY, framingRect.left, framingRect.top, framingRect.right, framingRect.bottom);
    }

    
    public String getScanViewTitle() {
        return TextUtils.isEmpty(scanViewTitle) ? "扫描二维码" : scanViewTitle;
    }

    public void drawViewfinder() {
        invalidate();
    }

}

attrs.xml
自定义属性


    
        
        
        
        
        
        
        
        
        
        
        
        
    

到此完成!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/659393.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号