google扫码库barcode-scanning的使用

1 篇文章 0 订阅
1 篇文章 0 订阅

一、加入barcode-scanning库

//捆绑模式扫码
implementation 'com.google.mlkit:barcode-scanning:17.1.0'

二、编写扫码分析类,用于分析扫码数据并回调方法返回结果

package com.gnetek.monitor.adapter

import android.util.Log
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import com.google.mlkit.vision.barcode.BarcodeScannerOptions
import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.common.InputImage

/**
 * @Description 扫码分析器
 * @Author Darren Huang
 * @Date 2023-06-14 10:57
 */
class QRCodeAnalyzer(private val listener: (List<Barcode>) ->Unit) : ImageAnalysis.Analyzer {
    companion object {
        private const val TAG = "QRCodeAnalyzer"
    }

    @androidx.annotation.OptIn(androidx.camera.core.ExperimentalGetImage::class)
    override fun analyze(imageProxy: ImageProxy) {
        val image = imageProxy.image
        image?.let {
            val inputImage = InputImage.fromMediaImage(it, imageProxy.imageInfo.rotationDegrees)
            processImage(inputImage, imageProxy)
        }
    }

    //设置扫码类型,支持同时设置多个
    private val options = BarcodeScannerOptions.Builder()
        .setBarcodeFormats(Barcode.FORMAT_CODE_128)//条形码
//        .setBarcodeFormats(Barcode.FORMAT_QR_CODE)//二维码
        .build()
    private val scanner = BarcodeScanning.getClient(options)

    private fun processImage(image: InputImage, imageProxy: ImageProxy) {
        scanner.process(image)
            .addOnSuccessListener(listener)
            .addOnFailureListener {
                Log.e(TAG, "processImage: ${it.message}")
            }
            .addOnCompleteListener {
                imageProxy.close()
            }
    }
}

三、扫码的activity,调用相机

package com.gnetek.monitor.ui.activity

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.content.ContextCompat
import com.gnetek.monitor.R
import com.gnetek.monitor.adapter.QRCodeAnalyzer
import com.gnetek.monitor.databinding.ActivityScannerBinding
import com.gnetek.monitor.utils.StringUtil
import com.gnetek.monitor.base.BaseActivity
import java.util.concurrent.Executors

class ScannerActivity : BaseActivity() {

    companion object {
        private const val TAG = "ScannerActivity"
    }

    private val viewBinding: ActivityScannerBinding by lazy { ActivityScannerBinding.inflate(layoutInflater) }

    // 解析数据 Executor
    private val cameraExecutor by lazy { Executors.newSingleThreadExecutor() }

    private lateinit var requestPermissionLauncher: ActivityResultLauncher<Array<String>>
    override fun onCreate(savedInstanceState: Bundle?) {
        // 创建一个ActivityResultLauncher对象,用于请求权限
        requestPermissionLauncher = registerForActivityResult(
            ActivityResultContracts.RequestMultiplePermissions()
        ) { permissions ->
            if (permissions.containsValue(false)) {
                // 如果用户拒绝了权限,则需要向用户解释为什么需要该权限
                xToasts(R.string.setup_station_info_image_permission, 0)
            } else {
                // 已经授权,执行相关操作
                Log.e(TAG, "onCreate: 已经授权,执行相关操作")
                startCamera()
            }
        }
        super.onCreate(savedInstanceState)
    }

    override fun viewBinding() {
        setContentView(viewBinding.root)
    }

    override fun initView() {
        super.initView()
        //检查相机权限
        val bool = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
        if(bool) {
            startCamera()
        }else {//申请相机权限
            requestPermissionLauncher.launch(arrayOf(Manifest.permission.CAMERA))
        }
    }

    // 初始化相机和扫码
    private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)

        cameraProviderFuture.addListener({
            val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
            // Preview
            val preview = Preview.Builder()
                .build()
                .also {
                    it.setSurfaceProvider(viewBinding.viewFinder.surfaceProvider)
                }

            // 默认选择后摄
            val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
            val imageAnalyzer = ImageAnalysis.Builder()
                .build()
                .also {
                    it.setAnalyzer(cameraExecutor, QRCodeAnalyzer { list ->
                        // 扫码结果,这里需根据项目做去重处理
                        val codes = list.filter { StringUtil.isNotBlank(it.rawValue.toString()) }.distinct().joinToString(separator=",") { it.rawValue.toString() }
                        Log.d(TAG, "startCamera barcode: $codes")
                        if(StringUtil.isNotBlank(codes)) {
                            val intent = Intent()
                            intent.putExtra("codes", codes)
                            setResult(RESULT_OK, intent)
                            finish()
                        }
                    })
                }

            try {
                // Unbind use cases before rebinding
                cameraProvider.unbindAll()
                // Bind use cases to camera
                cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalyzer)
            } catch (exc: Exception) {
                Log.e(TAG, "Use case binding failed", exc)
            }

        }, ContextCompat.getMainExecutor(this))
    }
}

四、BaseActivity类

package com.gnetek.monitor.base
import android.os.Bundle
import android.view.Gravity
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
import com.gnetek.monitor.R
import com.xuexiang.xui.utils.WidgetUtils
import com.xuexiang.xui.utils.XToastUtils
import com.xuexiang.xui.widget.dialog.LoadingDialog
import com.xuexiang.xui.widget.toast.XToast
import org.jetbrains.anko.*

/**
 * activity的基类
 * @author Darren
 * @date 2023/05/06
 * @constructor 创建[BaseActivity]
 */
abstract class BaseActivity : AppCompatActivity(), AnkoLogger {

    /**
     * 加载中
     */
    protected lateinit var baseLoadingDialog: LoadingDialog

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        XToast.Config.get() //位置设置为居中
            .setGravity(Gravity.CENTER)
        viewBinding()
        initView()
        initListener()
        initData()
        info { "onCreate" }
    }

    /**
     * 绑定布局
     */
    abstract fun viewBinding()

    /**
     * 初始化view
     */
    protected open fun initView(){
        baseLoadingDialog = WidgetUtils.getLoadingDialog(this)
            .setIconScale(0.4f)
            .setLoadingSpeed(8)
    }

    /**
     * 初始化监听
     */
    protected open fun initListener() {

    }

    /**
     * 初始化数据
     */
    protected open fun initData() {

    }

    /**
     * FragmentManager的扩展函数,它将一个带有接受者的Lambda函数作为传入的参数,而这个FragmentTransaction就是接收者对象
     */
    inline fun FragmentManager.inTransaction(func: FragmentTransaction.() -> FragmentTransaction) {
        beginTransaction().func().commit()
    }

    fun FragmentActivity.addFragment(fragment: Fragment, frameId: Int){
        supportFragmentManager.inTransaction { add(frameId, fragment) }
    }


    fun FragmentActivity.replaceFragment(fragment: Fragment, frameId: Int) {
        supportFragmentManager.inTransaction{replace(frameId, fragment)}
    }

    /**
     * 线程安全的提示信息
     */
    fun toasts(message:String){
        runOnUiThread{longToast(message)}
    }

    /**
     * 线程安全的提示信息
     */
    fun toasts(messageRes:Int){
        runOnUiThread{longToast(messageRes)}
    }



    /**
     * 线程安全的提示信息
     * 0->error 1->success 2->info 3->warning 4->toast
     */
    fun xToasts(message: String, position: Int=4){
        try {
            runOnUiThread {
                when (position) {
                    0 -> XToastUtils.error(message)
                    1 -> XToastUtils.success(message)
                    2 -> XToastUtils.info(message)
                    3 -> XToastUtils.warning(message)
                    4 -> XToastUtils.toast(message)
                }
            }
        }catch (e: IllegalStateException){
            e.printStackTrace()
        }
    }

    /**
     * 线程安全的提示信息
     * 0->error 1->success 2->info 3->warning 4->toast
     */
    fun xToasts(messageRes: Int, position: Int=4){
        try {
            runOnUiThread {
                when (position) {
                    0 -> XToastUtils.error(messageRes)
                    1 -> XToastUtils.success(messageRes)
                    2 -> XToastUtils.info(messageRes)
                    3 -> XToastUtils.warning(messageRes)
                    4 -> XToastUtils.toast(messageRes)
                }
            }
        }catch (e: IllegalStateException){
            e.printStackTrace()
        }
    }

    /**
     * 开启activity并且关闭当前界面,在打开新的界面中返回不用显示当前界面时用
     */
    inline fun <reified T: BaseActivity> startActivityAndFinish(){
        startActivity<T>()
        finish()
    }

    /**
     * 从左开始活动
     */
    inline fun <reified T: BaseActivity> startActivityFromLeft(){
        startActivity<T>()
        //从左到右切入
        overridePendingTransition(R.anim.slide_in_from_left,R.anim.slide_out_to_right)
    }


    /**
     * 从右开始活动
     */
    inline fun <reified T: BaseActivity> startActivityFromRight(){
        startActivity<T>()
        //从右到左切入
        overridePendingTransition(R.anim.slide_in_from_right,R.anim.slide_out_to_left)
    }

    /**
     * 加载中
     */
    fun showLoading(){
        runOnUiThread {
            baseLoadingDialog.show()
        }
    }
    /**
     * 加载完成
     */
    fun hideLoading(){
        runOnUiThread {
            baseLoadingDialog.dismiss()
        }
    }

    /**
     * 获得焦点
     * @param [view] 视图
     */
    fun getFocus(view: View){
        runOnUiThread {
            view.requestFocus()
        }
    }

    /**
     * 销毁
     */
    override fun onDestroy() {
        XToast.Config.get() //位置还原
            .resetGravity()
        super.onDestroy()
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值