对ZXing进行封装,整合成一个调用简单的Scanner接口

        最近有用到扫描二维码和条形码的需求,看到当前主要有两个比较有名的开源库ZBar和ZXing,怀着对Google的仰慕之心,并且凭着对二维码扫码的优势,最终决定使用ZXing来进行开发。

        网上已有很多大神对ZXing的使用进行了详解,但是并没有独立成一个模块。本文的思路是将ZXing再次封装,整合成一个调用简单的Scanner,仅仅对外暴露出几个回调的接口,使其作为一个独立的插件来使用,对项目的耦合性尽可能的低。

        至于具体实现,本人由于水平有限,思前想后,最终采用广播来实现(如有大神有更好的实现方式,欢迎指教)。核心思想是用一个Scanner类来进行对扫码Activity的管理,包括该Activity的启动、扫码结果的处理、扫码错误以及用户取消事件的处理和最终Activity的关闭等。

        Scanner类中的处理

        1. Scanner 打开时的处理:启动扫码的Activity,注册广播,该广播接收器中实现了对ScannerListener的监听回调

    public void open(){
        Intent intent = new Intent(context, MipcaActivityCapture.class);
        intent.putExtra(TIMEOUT, mTimeout);
        context.startActivity(intent);
        registerMyBroadcastReceiver();
    }

    private void registerMyBroadcastReceiver(){
        if(!isBroadcastRegistered) {
            isBroadcastRegistered = !isBroadcastRegistered;
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(QRCodeScanner.SCAN_INTENT_ACTION);
            context.registerReceiver(receiver, intentFilter);
        }
    }

    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().endsWith(SCAN_INTENT_ACTION)) {
                int flag = intent.getIntExtra("FLAGS", ERROR_FLAG);
                switch ( flag ){
                    case SUCCESS_FLAG:
                        qrCodeStr = intent.getStringExtra("QR_CODE_STR");
                        if(listener != null) {
                            listener.onReadSuccess(qrCodeStr);
                        }
                        break;
                    case CANCEL_FLAG:
                        if(listener != null){
                            listener.onCancel();
                        }
                        break;
                    case ERROR_FLAG:
                    default:
                        if(listener != null){
                            listener.onReadError();
                        }
                        break;
                }
            }
        }
    };
        2. Scanner开始扫码时的处理:实现监听器接口

    public void start(ScannerListener listener){
        this.listener = listener;
    }

    public interface ScannerListener{
        void onReadSuccess(String result);
        void onReadError();
        void onCancel();
    }
        3. Scanner关闭时的处理:取消广播的注册,并向扫码Actiivty发送关闭自身的广播(该Scanner的设计思想是只能通过此种方式关闭扫码Activity,禁止其他方式来关闭)

    public void close(){
        unRegisterMyBroadcastReceiver();
        Intent intent = new Intent(MipcaActivityCapture.CLOSE_SCANNER_INTENT_ACTION);
        context.sendBroadcast(intent);
    }

    private void unRegisterMyBroadcastReceiver(){
        if(isBroadcastRegistered) {
            isBroadcastRegistered = !isBroadcastRegistered;
            context.unregisterReceiver(receiver);
        }
    }

        扫码Activity中的处理

        1. 在该Activity 的onCreate方法中注册自己的销毁广播

    private void registerDestroyActivityReceiver(){
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(CLOSE_SCANNER_INTENT_ACTION);
        registerReceiver(mDestroyActivityReceiver, intentFilter);
    }

    private BroadcastReceiver mDestroyActivityReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
           if(intent.getAction().equals(CLOSE_SCANNER_INTENT_ACTION)){
                finish();
            }
        }
    };

        2.在扫码结果处理的代码中根据扫码结果发送扫码成功或失败的广播

    /**
     * 处理扫描结果
     * @param result
     * @param barcode
     */
    public void handleDecode(Result result, Bitmap barcode) {
        inactivityTimer.onActivity();
        playBeepSoundAndVibrate();
        String resultString = result.getText();
        if(TextUtils.isEmpty(resultString)){
            Toast.makeText(MipcaActivityCapture.this, "Scan failed!", Toast.LENGTH_SHORT).show();
            sendScanErrorBroadcast();
        }else{
            sendSuccessBroadcast(resultString);
        }
    }

    private void sendSuccessBroadcast(String qrcodeStr){
        Intent intent = new Intent(QRCodeScanner.SCAN_INTENT_ACTION);
        intent.putExtra("FLAGS", QRCodeScanner.SUCCESS_FLAG);
        intent.putExtra("QR_CODE_STR", qrcodeStr);
        sendBroadcast(intent);
    }

    public void sendScanErrorBroadcast(){
        Intent intent = new Intent(QRCodeScanner.SCAN_INTENT_ACTION);
        intent.putExtra("FLAGS", QRCodeScanner.ERROR_FLAG);
        sendBroadcast(intent);
    }
        3.在用户点击“返回”按钮或“返回”键时发送“用户取消操作事件”的广播

    private void sendCancelBroadcast(){
        Intent intent = new Intent(QRCodeScanner.SCAN_INTENT_ACTION);
        intent.putExtra("FLAGS", QRCodeScanner.CANCEL_FLAG);
        sendBroadcast(intent);
    }
        4.在扫码Activity的onDestroy()方法中取消销毁广播的注册

    @Override
    protected void onDestroy() {
        inactivityTimer.shutdown();
        super.onDestroy();
        unregisterReceiver(mDestroyActivityReceiver);
    }
        至此,Scanner的封装已经完成,让我们来体会一下该Scanner使用时的简洁和优雅吧

    private void startScanner(){
        final QRCodeScanner qrCodeScanner = new QRCodeScanner(this);
        qrCodeScanner.open();
        qrCodeScanner.start(new QRCodeScanner.ScannerListener() {
            @Override
            public void onReadSuccess(String result) {
                qrCodeScanner.close();
                tvQRCode.setText(result);
                Log.i("Tag", "read success...");
            }

            @Override
            public void onReadError() {
                qrCodeScanner.close();
                Log.i("Tag", "read error or time out...");
            }

            @Override
            public void onCancel() {
                qrCodeScanner.close();
                Log.i("Tag", "user canceled...");
            }
        });
    }
        源码下载地址: 对ZXing封装的Scanner源码


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值