google扫码库barcode-scanning的使用

2023-11-09

一、加入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()
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

google扫码库barcode-scanning的使用 的相关文章

  • 如何快速自动发送FCM或APNS消息?

    我正在开发一项后端服务 通过 FCM 或 APNS 向移动应用程序发送推送通知 我想创建一个可以在一分钟内运行的自动化测试 并验证服务器是否可以成功发送通知 请注意 我不一定需要检查通知是否已送达 只需检查 FCM 或 APNS 是否已成功
  • Android Studio 3.0 Canary 9 - 无法解析包

    我在 Android Studio 3 0 Canary 9 中遇到几个错误 这些错误是 无法解析 android 软件包 下面列出了一些错误 我刚刚安装了 SDK 的所有额外软件包 但仍然收到 gradle 构建错误 Error 82 1
  • StrictMode 策略违规:我的应用程序中存在 android.os.strictmode.LeakedClosableViolation?

    Android 开发新手 第一次在我的应用程序上尝试 StrictMode 我注意到以下内容 并想知道这是否是我的应用程序或库中的问题 我不太清楚 谢谢你 D StrictMode StrictMode policy violation a
  • 如何重试已消耗的 Observable?

    我正在尝试重新执行失败的已定义可观察对象 一起使用 Retrofit2 和 RxJava2 我想在单击按钮时重试特定请求及其订阅和行为 那可能吗 service excecuteLoginService url tokenModel Ret
  • android中向sqlite中插入大量数据

    目前 我必须一次向我的 Android 中插入超过 100 亿条数据 然而 内存不足的问题会使程序崩溃 sqlite 插入测试非常简单 只需使用 for 循环生成 sql 插入命令并通过 开始 和 提交 进行包装 private Array
  • 在 Android Studio 中,为什么我必须在模拟器中单击“运行应用程序”两次才能启动应用程序?

    在 Android Studio 中 当我按播放按钮在 Android 模拟器上安装并运行应用程序时 大约 5 10 秒后 我在屏幕底部收到一条消息 显示 安装成功 但应用程序实际上并未运行在模拟器上 我必须再次按下播放按钮 这是非常令人沮
  • Android 30+ 中的视频捕获意图 - 只有所有者才能与待处理项目交互

    我正在尝试在我的应用程序上捕获视频 它可以在 android API 30 以下运行 但不能在 30 以上运行 似乎在 sdk 30 之后 android 不允许完全读取外部存储 作用域存储 我目前遇到这个错误 java lang Ille
  • Android 后退按钮无法与 Flutter 选项卡内的导航器配合使用

    我需要在每个选项卡内有一个导航器 因此当我推送新的小部件时 选项卡栏会保留在屏幕上 代码运行得很好 但是 android 后退按钮正在关闭应用程序而不是运行 Navigator pop import package flutter mate
  • 无法获取log.d或输出Robolectrict + gradle

    有没有人能够将 System out 或 Log d 跟踪从 robolectric 测试输出到 gradle 控制台 我在用Robolectric Gradle 测试插件 https github com robolectric robo
  • Android Activity 生命周期函数基础知识

    我正在测试这段代码 它显示活动所处的状态 public class Activity101Activity extends Activity String tag Lifecycle Called when the activity is
  • Android 模拟器插件无法初始化后端 EGL 显示

    我在 Cloudbees 上设置了 Jenkins 作业 并且可以在那里成功签出并编译我的 Android 项目 现在我想在 android 模拟器中运行一些 JUnit 测试并添加 Android 模拟器插件 我将 显示模拟器窗口 选项设
  • 在 java 类和 android 活动之间传输时音频不清晰

    我有一个android活动 它连接到一个java类并以套接字的形式向它发送数据包 该类接收声音数据包并将它们扔到 PC 扬声器 该代码运行良好 但在 PC 扬声器中播放声音时会出现持续的抖动 中断 安卓活动 public class Sen
  • 在 HTTPResponse Android 中跟踪重定向

    我需要遵循 HTTPost 给我的重定向 当我发出 HTTP post 并尝试读取响应时 我得到重定向页面 html 我怎样才能解决这个问题 代码 public void parseDoc final HttpParams params n
  • Android:捕获的图像未显示在图库中(媒体扫描仪意图不起作用)

    我遇到以下问题 我正在开发一个应用程序 用户可以在其中拍照 附加到帖子中 并将图片保存到外部存储中 我希望这张照片也显示在图片库中 并且我正在使用媒体扫描仪意图 但它似乎不起作用 我在编写代码时遵循官方的Android开发人员指南 所以我不
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 我想实现下面的布局,按钮应该在屏幕底部,当惰性列被填充时,按钮不应该出去

    顶部有惰性列 惰性列下方有输入电话号码布局并从电话簿布局添加联系人 我希望当未添加联系人时此布局位于顶部 当我添加大量联系人时输入电话号码并添加电话簿布局中的联系人会随着惰性列滚动并移出屏幕 我不让他们走出屏幕 当接触较多时 它们必须粘在底
  • 字符串数组文本格式化

    我有这个字符串 String text Address 1 Street nr 45 Address 2 Street nr 67 Address 3 Street nr 56 n Phone number 000000000 稍后将被使用
  • Android 中麦克风的后台访问

    是否可以通过 Android 手机上的后台应用程序 服务 持续监控麦克风 我想做的一些想法 不断聆听背景中的声音信号 收到 有趣的 音频信号后 执行一些网络操作 如果前台应用程序需要的话 后台应用程序必须能够智能地放弃对麦克风的访问 除非可
  • 一次显示两条Toast消息?

    我希望在一个位置显示一条 Toast 消息 并在另一位置同时显示另一条 Toast 消息 多个 Toast 消息似乎总是按顺序排队和显示 是否可以同时显示两条消息 是否有一种解决方法至少可以提供这种外观并且不涉及扰乱活动布局 Edit 看来
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591

随机推荐

  • pymysql的使用

    pymysql是从Python连接到MySQL数据库服务器的接口 其官方文档为 https pymysql readthedocs io en latest 安装 pip install pymysql 对于数据库的操作 我们一般是这样的操
  • 正在开发应用于Maxthon、TT等多页面浏览器的页面模式

    经过大量的用户调查 我们发现 有不少朋友使用了Maxthon 腾讯TT 世界之窗等基于IE的多页面浏览器使用WEBCHAT 而这种模式下弹出窗口将变成一个新页面 用起来不方便
  • 如何查看支付宝旗下的天弘基金一共有多少只?分别是什么?

    如何查看支付宝旗下的天弘基金一共有多少只 分别是什么 2020年 股市风格突变 相对股市个股的跌宕起伏 基金的收益可谓一枝独秀 下面我们将对基金进行研究 看看我们可以获取数据能否到什么程度 利用tushare的数据接口就可以获取基金的名称
  • 排序类算法

    文章目录 利用vector进行排序 数字类元素 字符串类元素 利用其他STL容器排序 map set priority queue 利用vector进行排序 数字类元素 每个元素一般包含多个条件 利用lambda编写特定排序条件 用sort
  • 转:Ogre TerrainGroup地形赏析

    转 Ogre TerrainGroup地形赏析 1 1 参考 http www ogre3d org tikiwiki tiki index php page Ogre Terrain System http www ogre3d org
  • VS2017找不到QT头文件

    一 我的电脑右键属性 高级系统设置 环境变量 增加环境变量Qt INCLUDEPATH 值为QT的头文件目录 二 重启VS 发现波纹线不见了 证明设置环境变量后VS能识别到QT头文件了 原理是 vs导入qt项目附加包含目录继承值有Qt IN
  • (202301)pytorch图像分类全流程实战Task6:可解释性分析、显著性分析

    Task6 可解释性分析 显著性分析 对B站up同济子豪兄的图像分类系列的学习 大佬的完整代码在GitHub开源 2022年人工智能依旧飞速发展 从传统机器学习模型到如今以 炼丹 为主的深度神经网络 代表着模型拟合度与模型可解释性各自的发展
  • MySQL学习(十六):数据类型之日期与时间类型

    数据类型之日期与时间类型 日期与时间是重要的信息 在我们的系统中 几乎所有的数据表都用得到 原因是客户需要知道数据的时间标签 从而进行数据查询 统计和处理 类型 名称 字节 日期格式 最小值 最大值 YEAR 年 1 YYYY或YY 190
  • Linux系统管理(六)高级存储管理

    目录 一 逻辑卷 二 lvm逻辑管理器 lvm建立 lvm拉伸 lvm缩减 lvm删除 lvm快照 三 vdo虚拟数据优化器 vdo建立 使用vdo设备 测试vdo性能 设置vdo开机自启动 vdo设备的删除 一 逻辑卷 pv 物理卷 被处
  • DRM——学习篇0:概念认识

    刚开始学习 记忆不是很好 容易忘 边学边记 阅读的速度会比较慢 看的会比较仔细 这边主要参考以下博客 前辈们水平很高 写的很详细 详细的知识学习可查看以下链接 详细请看 蜗窝科技 http www wowotech net graphic
  • wpf 怎么用代码连接sql server

    在WPF中 可以使用C 代码来连接SQL Server 以下是连接SQL Server的一般步骤 首先 在项目中添加对System Data SqlClient命名空间的引用 在代码中创建SqlConnection对象 该对象表示与SQL
  • 18.tf坐标系广播与监听的实现

    学习视频 https www bilibili com video BV1zt411G7Vn p 18 广播器代码 获取海龟位置 广播world与海龟坐标系之间的tf数据 监听器代码 监听tf数据 并计算 发布turtle2的速度指令 一
  • FAPI专题-2:5G nFAPI接口 - 中文规范-2- 消息交互流程

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https mp csdn net mp blog creation editor 117588884 目录 第1章 简介 第2章 nFAP
  • MySQL开启远程访问权限

    默认情况下 MySQL只允许本地登录 即只能在安装MySQL环境所在的主机下访问 但是在日常开发和使用中 我们经常需要访问远端服务器的数据库 此时就需要开启服务器端MySQL的远程连接权限 1 生成环境 连接MySQL 2 查看MySQL当
  • 最言简意赅的strftime和strptime区分方式

    最近时常处理金融数据 最绕不过的就是对各种日期格式进行处理 其中用得最多的就是striptime和striftime 之前每用一次都得查一下用法 这次干脆完全弄清楚然后记下来 以下是最言简意赅的区分方式 strptime 将字符串转换为日期
  • 某团面试题:JVM 堆内存溢出后,其他线程是否可继续工作?

    转载 最近网上出现一个美团面试题 一个线程OOM后 其他线程还能运行吗 我看网上出现了很多不靠谱的答案 这道题其实很有难度 涉及的知识点有jvm内存分配 作用域 gc等 不是简单的是与否的问题 由于题目中给出的OOM java中OOM又分很
  • 谭铁牛院士:向生物学习 开启模式识别新突破

    人们在观察事物或现象的时候 常常要把各个相似的但又不完全相同的事物或现象组成一类 例如一个数字有不同的写法 对一个人来说 某一种写法虽然没有见过 但大脑却能自动将这个字识别出来 这种模式识别行为虽然人们早已司空见惯 在中国科学院院士谭铁牛看
  • 前端学习历程

    前言 还记得刚接触前端应该是两年前了吧 我就顺着回忆 慢慢写下我对前端的学习路程以及一些资源 初入坑 html css基础 这个是学习前端最基础的部分了 一开始看的是W3cschool 先看其中的html和css基础部分 一些常用标签 以及
  • Python常用的第三方库汇总【推荐】

    Python常用的第三方库汇总 pymysql 操作MySQL数据库 Flask 一个 Python 后端开发的微型框架 numpy 进行科学计算所需的基础包 pillow 非常好用的图像处理库 opencv python 图像处理库 Ma
  • google扫码库barcode-scanning的使用

    一 加入barcode scanning库 捆绑模式扫码 implementation com google mlkit barcode scanning 17 1 0 二 编写扫码分析类 用于分析扫码数据并回调方法返回结果 package