Android新兴扫码框架:XCodeScanner(最近更新2018-08-17)

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

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

目录

示例demo

Demo下载 示例效果
点此下载(1.7MB) 或扫描下面二维码
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.png

集成方式

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

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

使用方式

  • 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.7 2018/08/07

    1. 修复armeabi架构无法识别二维码的问题。
    2. 增加亮度反馈,可实现提示开启闪光灯功能。
    3. CameraScanner取消单例模式,增加单例信号量CameraLock解决可能产生的相机并发操作。
    4. GraphicDecoder新增setCodeTypes接口指定识别的类型。
    5. MaskConstraintLayoutMaskRelativeLayout新增frame_viewid属性,用于指定绘制阴影的View(便于开发者使用自定义的扫描框)。
    6. demo界面调整。
    7. 发布开源库:cn.simonlee.xcodescanner:zbar:1.1.7

    补充:

    1. ZBarDecoder构造方法调整。
    2. CameraScanner中的setSurfaceTexture(SurfaceTexture surfaceTexture)接口更名为setPreviewTexture(SurfaceTexture surfaceTexture),便于理解。
    3. CameraScanner新增enableBrightnessFeedback(boolean enable)接口,设置是否开启亮度回馈。
    4. CameraListener新增cameraBrightnessChanged(int brightness)接口,对亮度变化进行回馈。
    5. 移除BaseHandler
  • 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. 暂停/延时解码接口从CameraScanner迁移到GraphicDecoderCameraScanner可能因为异步导致暂停后继续回调decodeSuccess接口。
    5. 发布开源库: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.3
  • V1.1.2 2018/04/24

    1. 修复ZBarDecoder中设置解码格式无效的问题。
  • V1.1.1 2018/04/16

    1. ScannerFrameView增加高占比属性,可设置相对父容器高的占比。
  • 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来点鼓励吧

Author E-mail GitHub WeChat
Simon Lee jmlixiaomeng@163.com XCodeScanner
wechat
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容