Giter Site home page Giter Site logo

simon-leeeeeeeee / xcodescanner Goto Github PK

View Code? Open in Web Editor NEW
653.0 14.0 88.0 12.56 MB

A new frame for decode QR code and bar code on Android. It's faster, simpler and more accurate.

License: Apache License 2.0

Java 1.61% Makefile 3.54% C 61.14% Assembly 0.04% C++ 6.38% Shell 18.78% M4 3.89% Batchfile 0.32% Objective-C 2.04% Roff 1.80% HTML 0.29% sed 0.16%
android zbar qrcode-scanner barcode-scanner

xcodescanner's Introduction

🌟 XCodeScanner

一个Android平台更快更简单更精准的条形码及二维码解析框架。采用ZBar解析图像数据,兼容Android4.0 (API14)及以上版本。

English

目录

示例demo

Demo下载 示例效果
点此下载 或扫描下面二维码
demo
gif

功能介绍

本项目基于ZBar进行开发,分别对视图、相机、解码三个方面进行了封装,同时降低三者之间的耦合,增加可灵活配置性。

  • 视图

    • 自定义AdjustTextureView,继承自TextureView,开放setImageFrameMatrix接口,可根据自身尺寸、图像帧宽高及旋转角度对图像进行校正,解决预览画面变形等异常问题。
    • 自定义ScannerFrameView,继承自View,可通过xml属性或接口自定义扫描框、四个角及扫描线的尺寸、颜色、动画等,具体属性使用参考源码注解
    • 自定义MaskRelativeLayout&MaskConstraintLayout,分别继承自RelativeLayout&ConstraintLayout,用于绘制扫描框外部阴影。
  • 相机

    • 兼容android.hardware.camera2android.hardware.Camera两版API。
    • 子线程开启camera,防止阻塞主线程造成界面跳转卡顿。
    • 采用单例信号量控制,防止多个实例同时操作相机引发异常。
    • 加入亮度回馈,智能提示开启闪光灯。
    • 开放扫码框Rect设置接口,根据预览尺寸、图像帧尺寸、预览方向计算出扫码框在图像帧上的实际位置,以指定图像识别区域。
    • TextureReader代替ImageReader,采用openGL绘制图像纹理,主要解决ImageReader实时输出YUV格式图像时预览掉帧严重的问题。
  • 解码

    • 支持指定图像区域识别。
    • 开放条码类型配置接口,可任意指定需要识别的条码类型。
    • 解码回调结果包含条码类型、条码精度,可配置脏数据过滤规则。

UML类图

uml

集成方式

在module的build.gradle中添加如下代码

    dependencies {
        implementation 'cn.simonlee.xcodescanner:zbar:1.1.10'
    }

使用方式

  • STEP.1

    在Activity的onCreate方法中获取CameraScanner实例,并对CameraScanner和TextureView设置监听

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scan_constraint);
        mTextureView = findViewById(R.id.textureview);
        mTextureView.setSurfaceTextureListener(this);
        /*
        * 注意,SDK21的设备是可以使用NewCameraScanner的,但是可能存在对新API支持不够的情况,比如红米Note3(双网通Android5.0.2)
        * 开发者可自行配置使用规则,比如针对某设备型号过滤,或者针对某SDK版本过滤
        * */
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mCameraScanner = new NewCameraScanner(this);
        } else {
            mCameraScanner = new OldCameraScanner(this);
        }
    }
  • STEP.2

    在onSurfaceTextureAvailable回调中设置SurfaceTexture及TextureView的宽高,然后开启相机

    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        mCameraScanner.setPreviewTexture(surface);
        mCameraScanner.setPreviewSize(width, height);
        mCameraScanner.openCamera(this);
    }
  • STEP.3

    在openCameraSuccess回调中设置图像帧的宽高及旋转角度,获取ZBarDecoder实例设置给CameraScanner

    public void openCameraSuccess(int frameWidth, int frameHeight, int frameDegree) {
        mTextureView.setImageFrameMatrix(frameWidth, frameHeight, frameDegree);
        if (mGraphicDecoder == null) {
            mGraphicDecoder = new ZBarDecoder(this);//可使用二参构造方法指定条码识别的类型
        }
        //调用setFrameRect方法会对识别区域进行限制,注意getLeft等获取的是相对于父容器左上角的坐标,实际应传入相对于TextureView左上角的坐标。
        mCameraScanner.setFrameRect(mScannerFrameView.getLeft(), mScannerFrameView.getTop(), mScannerFrameView.getRight(), mScannerFrameView.getBottom());
        mCameraScanner.setGraphicDecoder(mZBarDecoder);
    }
  • STEP.4

    在ZBarDecoder的decodeSuccess回调中获取解析结果,开发者可根据回传的条码类型及精度自定义脏数据过滤规则

    public void decodeSuccess(int type, int quality, String result) {
        ToastHelper.showToast("[类型" + type + "/精度" + quality + "]" + result, ToastHelper.LENGTH_SHORT);
    }
  • STEP.5

    在Activity的onDestroy方法中关闭相机和解码

    public void onDestroy() {
        mCameraScanner.setGraphicDecoder(null);
        mCameraScanner.detach();
        if (mGraphicDecoder != null) {
            mGraphicDecoder.setDecodeListener(null);
            mGraphicDecoder.detach();
        }
        super.onDestroy();
    }

注意事项

  • Tips.1

    在Activity的onPause方法中关闭相机

    public void onPause() {
        mCameraScanner.closeCamera();
        super.onPause();
    }
  • Tips.2

    在Activity的onRestart方法中开启相机

    public void onRestart() {
        //部分机型在后台转前台时会回调onSurfaceTextureAvailable开启相机,因此要做判断防止重复开启
        if (mTextureView.isAvailable()) {
            mCameraScanner.setPreviewTexture(mTextureView.getSurfaceTexture());
            mCameraScanner.setPreviewSize(mTextureView.getWidth(), mTextureView.getHeight());
            mCameraScanner.openCamera(this.getApplicationContext());
        }
        super.onRestart();
    }
  • Tips.3

    设置扫码框识别区域时,要考虑到扫码框的margin和padding属性。

更新计划

  • 结合OpenCV,提供二维码检测、二维码定位、角度校正、图像滤波等支持,以解决复杂图形的识别问题。
  • 增加Zxing支持。
  • 增加二维码生成功能。

版本记录

  • V1.1.10 2018/09/21

    1. 修复OldCameraScanner中判断闪光灯状态时可能引起的空指针异常。
    2. 亮度回馈由每20帧回调一次平均值改为每帧进行回调。
    3. 依赖版本更新:cn.simonlee.xcodescanner:zbar:1.1.10
  • V1.1.9 2018/09/19

    1. 修复在V1.1.8中NewCameraScanner关闭相机时提前释放SurfaceTexture的问题。
    2. 依赖版本更新:cn.simonlee.xcodescanner:zbar:1.1.9
  • V1.1.8 2018/09/10

    1. ZBarDecoder中在子线程实例化ImageScanner对象,避免在主线程中进行System.loadLibrary()
    2. 修复NewCameraScanner中关闭相机时未释放Surface对象的问题。
    3. 依赖版本更新:cn.simonlee.xcodescanner:zbar:1.1.8
  • V1.1.7 2018/08/07

    1. 修复armeabi架构无法识别二维码的问题。
    2. 增加亮度反馈,可实现提示开启闪光灯功能。
    3. OldCameraScannerNewCameraScanner取消单例模式,增加单例信号量CameraLock解决可能产生的相机并发操作。
    4. GraphicDecoder新增setCodeTypes(int[] codeType)接口指定识别的类型。
    5. MaskConstraintLayoutMaskRelativeLayout新增frame_viewid属性,用于指定绘制阴影的View(便于开发者使用自定义的扫描框)。
    6. ZBarDecoder构造方法调整。
    7. CameraScanner中的setSurfaceTexture(SurfaceTexture surfaceTexture)接口更名为setPreviewTexture(SurfaceTexture surfaceTexture)
    8. CameraScanner新增enableBrightnessFeedback(boolean enable)接口,设置是否开启亮度回馈。
    9. CameraListener新增cameraBrightnessChanged(int brightness)接口,对亮度变化进行回馈。
    10. 移除BaseHandler
    11. 依赖版本更新:cn.simonlee.xcodescanner:zbar:1.1.7
  • V1.1.6 2018/05/08

    1. GraphicDecoder增加本地图片识别接口。
    2. 废弃GraphicDecoder.DecodeListener中的decodeSuccess接口,改为decodeComplete
    3. CameraScanner新增闪光灯控制接口。
    4. 解决AdjustTextureView尺寸变化导致图像显示异常的问题。
    5. 依赖版本更新:cn.simonlee.xcodescanner:zbar:1.1.6
  • V1.1.5 2018/05/01

    1. 解决申请权限闪退的问题。
    2. 解决魅族MX5闪退的问题。
    3. 修改ZBarDecoderTextureReader的实现方式,降低CPU占用。
    4. 新增DebugZBarDecoder,继承自ZBarDecoder,便于示例程序进行兼容性测试。
    5. 暂停/延时解码接口从CameraScanner迁移到GraphicDecoderCameraScanner可能因为异步导致暂停后继续回调decodeSuccess接口。
    6. 依赖版本更新:cn.simonlee.xcodescanner:zbar:1.1.5
  • V1.1.4 2018/04/26

    1. 解决Android4.2退出时闪退的问题。
    2. 解决某些低端机型可能预览严重丢帧的问题。
    3. 解决OldCameraScanner默认没有开启解码的问题。
    4. 依赖版本更新:cn.simonlee.xcodescanner:zbar:1.1.4
  • V1.1.3 2018/04/25

    1. 解决部分x86设备闪退的问题。
    2. CameraScanner新增stopDecode()startDecode(int delay)接口,可暂停/延时解码。
    3. ZBar包名由com.simonlee.xcodescanner变更为cn.simonlee.xcodescanner
    4. 依赖版本更新:cn.simonlee.xcodescanner:zbar:1.1.3codescanner变更为xcodescanner,由此带来不便的敬请谅解。
  • V1.1.2 2018/04/24

    1. 解决ZBarDecoder中设置解码类型无效的问题。
  • V1.1.1 2018/04/16

    1. ScannerFrameView增加高占比属性,可设置相对父容器高的占比。
    2. 依赖版本更新:cn.simonlee.codescanner:zbar:1.1.1
  • V1.1.0   2018/04/16

    1. 重写ZBarDecoder,解决单线程池可能引起的条码解析延迟问题。
    2. 解决OldCameraScanner扫描框区域识别异常的问题。
  • V1.0.9 2018/04/14

    1. 解决NewCameraScanner扫描框区域识别异常的问题。
    2. 解决连续快速旋转屏幕时NewCameraScanner出现异常的问题。
  • V1.0.8 2018/04/13

    1. AutoFixTextureView更名为AdjustTextureView,重写图像校正方式。
    2. Camera2Scanner更名为NewCameraScanner
    3. 新增OldCameraScanner实现对Android5.0以下的支持。
    4. 下调minSdkVersion至14。
    5. 解决前后台切换,横竖屏切换可能产生的异常。
    6. NewCameraScanner中取消ImageReader的支持。
  • V1.0.7 2018/04/10

    1. 调整扫描框宽高计算方式,新增MaskConstraintLayout布局。
    2. 优化Camera2Scanner,解决后台切换导致的闪退问题。
  • V1.0.6 2018/04/09

    1. 调整代码结构,将扫码核心从app移植到zbar中。
  • V1.0.5 2018/03/29

    1. 增加帧数据的最大尺寸限制,避免因过高像素导致ZBar解析二维码失败。
    2. 屏蔽ZBar对DataBar(RSS-14)类型条码的支持,此类型实用性不高,且易产生误判。
  • V1.0.4 2018/03/27

    1. 修改ZBarDecoder,修复多线程可能的空指针异常。
    2. 修改GraphicDecoder,EGL14替换EGL10,解决部分机型不兼容的问题;解决多线程可能的空指针异常。
  • V1.0.3 2018/03/23

    1. 新增TextureReader,通过双缓冲纹理获取帧数据进行回调,代替ImageReader的使用。
    2. 修改GraphicDecoder,handler放到子类中去操作。
  • V1.0.2 2018/03/14

    1. 新增抽象类GraphicDecoder,将条码解析模块进行抽离。
    2. 新增ZBarDecoder,采用ZBar解析条码,并增加解析类型及解析精度设置。
    3. 修改ScannerFrameView,扫描线动画由属性动画实现。
    4. 修改Camera2Scanner,修复释放相机可能导致的异常,增加扫描框区域设置。
    5. 其他微调。
  • V1.0.1 2018/02/09

    1. 新增ScannerFrameLayout,为RelativeLayout的子类,可对扫描框的位置和大小进行设置。
    2. 修改ScannerFrameView,可对扫描框内部进行定制。
  • V1.0.0 2018/02/03 初次提交代码。

关于作者

这是我个人的第一个开源项目,在开源的过程中碰到了许多疑点难点,多处借鉴很多大神的成果。因为自己的疏忽没有预先做好参考记录,在这里向那些为开源默默奉献的大神们致敬!Thanks!

如果在使用过程中遇到了闪退、黑屏、无法识别、无法对焦、预览掉帧、内存泄漏等任何异常问题,欢迎提Issues!同时请尽量附上设备型号、android版本号、BUG复现步骤、异常日志、无法识别的图像等,我会尽快安排解决。(若回复不及时可直接微信)

如果您觉得有用,请动动小手给我一个Star来点鼓励:blush:

Author E-mail 博客 WeChat
Simon Lee [email protected] 简书 · 掘金 wechat

xcodescanner's People

Contributors

simon-leeeeeeeee avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xcodescanner's Issues

decodeForResult这个api的使用建议

我在使用void decodeForResult(Context context, Uri uri, int requestCode);这个api的时候发现不能识别相册中的二维码。
后来改用void decodeForResult(Bitmap bitmap, RectF rectClipRatio, int requestCode);也会有部分机器不能够识别,看了源码有一段话说对图片分辨率有要求小于等于1920 * 1080。于是乎,在onActivityResult相册返回的data通过getContentResolver().query获取图片路径并生成的bitmap一定要压缩才可以解析二维码。我最开始用data.getData()把获取到的uri传入最上面的那个decodeForResult在三星G9500手机上会报错的

提几个需求,求别打

  1. 同时支持zxing和zar,默认走zar,如果zbr识别失败走zxing
  2. 扫描的时候如果发现距离过远,自动方法二维码图像,类似于微信和支付宝那样
  3. 增加二维码和条形码的生成

非常感谢楼主的开源,是我目前看到的扫码项目中,干货非常十足的项目

魅族mx5运行报错

错误输出是
java.lang.RuntimeException: TextureReader Error! EGL MakeCurrent failure: EGL_BAD_MATCH
at com.simonlee.scanner.core.TextureReader.initEGL(TextureReader.java:242)
at com.simonlee.scanner.core.TextureReader.run(TextureReader.java:191)

华为mate9无法识别问题

在华为mate9手机上 无法扫码识别 同一手机上的微信、自带浏览器以及第三方浏览器对同一二维码都可识别。图片无法上传 只能手打了
设备名称:HUAWEI Mate9
手机型号:MHA-AL00
版本号:MHA-AL00C00B233
EMUI版本:5.0.1
Android版本:7.0

8.0.0系统 识别

今天用了下在华为8.0上识别,条形码识别很快,但是二维码识别不出来。

一些建议

首先觉得作者这个做的还可以,至少体验上比其他的库快。自己也想做类似的库,但对相关的api不太熟,思路不清晰。不过建议是可以提的。
1、预览框和外面上下左右的阴影,是否有必要分开做。而且这个布局比较简单,完全用不到约束布局,不建议有了MaskRelativeLayout,还搞一个MaskConstraintLayout。没必要,约束布局还要引入一个库,这对一个本身就是库的来说,不太好。建议删除,也不需要花时间在这上面。
2、不管是zxing还是zbar,都是只负责解码和生成码的,不涉及UI以及camera预览,以及拾取的图像回调,所以做这类库,也主要就是封装这些东西,至于怎么处理解码,可以写个接口,然后就可以自己选(图像数据回调给接口了,至于怎么解析,选择zxing还是zbar,可以动态控制,zbar太大啦)。可以参考下面这个库的设计:https://github.com/themaster-gh/BGAQRCode-Android-master
3、接口设计有点复杂。用这个库的的话,需要实现3个接口CameraScanner.CameraListener, TextureView.SurfaceTextureListener, GraphicDecoder.DecodeListener,其实我觉得可以合并成一个接口就好,这些接口的很多方法在库的内部实现就可以(因为代码都是固定的,没必要每次都copy一遍)。
4、好像没有闪光灯控制的接口。不过按照计划,这个也会加的。

旋转扫描角度会扫描不出结果

我指的角度是扫描框和二维码边框的角度。二维码是个正方形,扫码框也是个正方形,一般扫描,扫码框的四边和二维码的四边都是大致平行的,但转一下角度(45°左右),就会扫不出结果。
测试机型:
一加三。
安卓8.0.

二维码无法识别,条码识别正常

机器是Android设备,但不是手机,下面是一些log

cn.simonlee.xcodescanner.core.NewCameraScanner.setPreviewSize() mPreviewSize = 1080x1848
cn.simonlee.xcodescanner.core.NewCameraScanner.takeOrientation() mOrientation = 0
cn.simonlee.xcodescanner.core.NewCameraScanner.getBigEnoughSize() minWidth = 1848 , minHeight = 1080
cn.simonlee.xcodescanner.core.NewCameraScanner.initSurfaceSize() mSurfaceSize = 1920x1080
cn.simonlee.xcodescanner.core.NewCameraScanner.initTextureReader() mTextureReader = 1920x1080
cn.simonlee.demo.xcodescanner.ScanActivity.openCameraSuccess() frameWidth = 1080 , frameHeight = 1920 , frameDegree = 0
cn.simonlee.xcodescanner.view.AdjustTextureView.setImageFrameMatrix() frameWH = 1080x1920 , frameDegree = 0
cn.simonlee.xcodescanner.view.AdjustTextureView.setImageFrameMatrix()B XY = 1 : 1.038961
cn.simonlee.xcodescanner.core.NewCameraScanner.setFrameRect() mOrientation = 0 frameRect = 0-0-1080-1848
cn.simonlee.xcodescanner.core.NewCameraScanner.setFrameRect() mClipRectRatio = RectF(0.0, 0.0, 0.9625, 1.0)

混淆后报错

异常类型:java.lang.UnsatisfiedLinkError

异常信息:No implementation found for long cn.bertsir.zbar.Qr.Symbol.a() (tried Java_cn_bertsir_zbar_Qr_Symbol_a and Java_cn_bertsir_zbar_Qr_Symbol_a__)

关键方法:cn.bertsir.zbar.Qr.Symbol.a(Native Method)

混淆应该如何配置?

本来想用这个库的,但是引入都不成功。

Could not resolve all dependencies for configuration ':app:debugRuntimeClasspath'.
Could not determine artifacts for cn.simonlee.xcodescanner:zbar:1.1.8
Could not get resource 'https://jcenter.bintray.com/cn/simonlee/xcodescanner/zbar/1.1.8/zbar-1.1.8.aar'.
Could not HEAD 'https://jcenter.bintray.com/cn/simonlee/xcodescanner/zbar/1.1.8/zbar-1.1.8.aar'.
Connect to d29vzk4ow07wi7.cloudfront.net:443 [d29vzk4ow07wi7.cloudfront.net/54.230.118.75, d29vzk4ow07wi7.cloudfront.net/54.230.118.174, d29vzk4ow07wi7.cloudfront.net/54.230.118.24, d29vzk4ow07wi7.cloudfront.net/54.230.118.198] failed: Read timed out
Read timed out

RequestCode不能为负值,也不能大于16位bit值65536

MainActivity中:

 @Override
    public void onClick(View v) {
        int permissionState = ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
        if (permissionState == PackageManager.PERMISSION_GRANTED) {
            startScan(v.getId());
        } else {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, v.getId());
        }
    }

不能用v.getId()作为requestCode,会直接崩溃。
不过你这个扫起来确实很快。这类项目github上有不少,但没见过一个好用的(因为很多改别人的),或多或少都有下面几个问题:
1、预览变形,这个也要看机型,但不知有没有可以兼容所有机型的方法。
2、扫码慢,复杂一点的就扫不出来
3、还是兼容性,在有些机型上会崩溃,但不可能测试到每个机型的,所以写这个需要经验吧,不知你这个兼容性如何,能否用于生产环境。

自己继承扫不出来

根据你的demo继承引入zbar也不行
自己直接加上依赖都不行,打开相机就在那里等着完全扫不出来

为什么会报下面的错误

E/libEGL: call to OpenGL ES API with no current context (logged once per thread)
cn.simonlee.demo.xcodescanner.ScanActivity.onSurfaceTextureDestroyed()

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.