Android zxing扫码,在预览页面持续扫描

修改zxing里的CaptureManager,使扫描后不结束activity。

扫描activity的代码如下:

package com.byxc.scanning;

import android.app.Activity;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PersistableBundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.widget.TextView;

import com.journeyapps.barcodescanner.DecoratedBarcodeView;

/**
 * 扫描二维码
 * Created by ypp on 2018/5/16.
 */

public class ScanningActivity extends Activity {
    private final String TAG="ScanningActivity";
    private CustomerCaptureManager captureManager;//扫描
    private DecoratedBarcodeView dbv_custom;
    /**
     * 当前闪光灯是否打开了
     */
    private boolean isTorchOn=false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_scanning);
        dbv_custom=(DecoratedBarcodeView)findViewById(R.id.dbv_custom);

        //重要代码,初始化捕获
        initCapture();
//        isScanHandler.sendEmptyMessageDelayed(0,30000);//30秒未扫描到,提示

    }

    /**
     * 初始化捕捉
     */
    private void initCapture(){
        if(captureManager!=null){
            captureManager.onDestroy();
            captureManager=null;
        }
        captureManager = new CustomerCaptureManager(this,dbv_custom,scanningListener);
        captureManager.initializeFromIntent(getIntent(),null);
        captureManager.decode();
    }
    /**
     * 扫描结果监听
     */
    private CustomerCaptureManager.ScanningListener scanningListener=new CustomerCaptureManager.ScanningListener(){

        @Override
        public void scanResult(String result) {
            HLog.toast(ScanningActivity.this,result);
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    initCapture();
                }
            },500);
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        captureManager.onSaveInstanceState(outState);
    }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        return dbv_custom.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
    }
    public void onResume()
    {
        super.onResume();
        captureManager.onResume();
    }

    public void onPause()
    {
        super.onPause();
        captureManager.onPause();
    }

    /**
     * 切换闪光灯
     * @param view
     */
    public void openOrCloseTorch(View view) {
        if(isTorchOn){
            if(hasTorch()){
                TextView flash_btn=(TextView)findViewById(R.id.flash_btn);
                flash_btn.setBackgroundResource(R.drawable.close_flash_light_bg);
                flash_btn.setText(getResources().getString(R.string.open_flash_light));
                dbv_custom.setTorchOff();
            }

        }else{
            if(hasTorch()){
                TextView flash_btn=(TextView)findViewById(R.id.flash_btn);
                flash_btn.setBackgroundResource(R.drawable.open_flash_light_bg);
                flash_btn.setText(getResources().getString(R.string.close_flash_light));
                dbv_custom.setTorchOn();
            }

        }
        isTorchOn=!isTorchOn;
    }
    /**
     * 判断是否有闪光灯
     * @return
     */
    public boolean hasTorch(){
        return getApplication().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
    }
}

CustomerCaptureManager代码:

package com.byxc.scanning;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.Display;
import android.view.Surface;
import android.view.Window;
import android.view.WindowManager;

import com.google.zxing.ResultMetadataType;
import com.google.zxing.ResultPoint;
import com.google.zxing.client.android.BeepManager;
import com.google.zxing.client.android.Intents;
import com.journeyapps.barcodescanner.BarcodeCallback;
import com.journeyapps.barcodescanner.BarcodeResult;
import com.journeyapps.barcodescanner.CameraPreview;
import com.journeyapps.barcodescanner.CaptureManager;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * 原CaptureManager不满足持续扫描的需求,所以进行修改
 * Created by ypp on 2018/5/24.
 */

public class CustomerCaptureManager {
    private static final String TAG = CaptureManager.class.getSimpleName();

    private static int cameraPermissionReqCode = 250;

    private Activity activity;
    private DecoratedBarcodeView barcodeView;
    private int orientationLock = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
    private static final String SAVED_ORIENTATION_LOCK = "SAVED_ORIENTATION_LOCK";
    private boolean returnBarcodeImagePath = false;

    private boolean destroyed = false;

    // Delay long enough that the beep can be played.
    // TODO: play beep in background
    private static final long DELAY_BEEP = 150;

//    private InactivityTimer inactivityTimer;
    private BeepManager beepManager;

    private Handler handler;

    private ScanningListener scanningListener;
    private BarcodeCallback callback = new BarcodeCallback() {
        @Override
        public void barcodeResult(final BarcodeResult result) {
            barcodeView.pause();
            beepManager.playBeepSoundAndVibrate();

            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    returnResult(result);
                }
            }, DELAY_BEEP);

        }

        @Override
        public void possibleResultPoints(List resultPoints) {

        }
    };

    private final CameraPreview.StateListener stateListener = new CameraPreview.StateListener() {
        @Override
        public void previewSized() {

        }

        @Override
        public void previewStarted() {
            HLog.v(TAG,"previewStarted","预览开始");
        }

        @Override
        public void previewStopped() {
            HLog.v(TAG,"previewStarted","预览停止");
        }

        @Override
        public void cameraError(Exception error) {
            displayFrameworkBugMessageAndExit();
        }
    };

    public CustomerCaptureManager(Activity activity, DecoratedBarcodeView barcodeView, ScanningListener scanningListener) {
        this.activity = activity;
        this.barcodeView = barcodeView;
        this.scanningListener=scanningListener;
        barcodeView.getBarcodeView().pause();//先停止,再重启
        barcodeView.getBarcodeView().resume();
        barcodeView.getBarcodeView().addStateListener(stateListener);

        handler = new Handler();

//        inactivityTimer = new InactivityTimer(activity, new Runnable() {
//            @Override
//            public void run() {
//                Log.d(TAG, "Finishing due to inactivity");
//                finish();
//            }
//        });

        beepManager = new BeepManager(activity);
    }

    /**
     * Perform initialization, according to preferences set in the intent.
     *
     * @param intent the intent containing the scanning preferences
     * @param savedInstanceState saved state, containing orientation lock
     */
    public void initializeFromIntent(Intent intent, Bundle savedInstanceState) {
        Window window = activity.getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        if (savedInstanceState != null) {
            // If the screen was locked and unlocked again, we may start in a different orientation
            // (even one not allowed by the manifest). In this case we restore the orientation we were
            // previously locked to.
            this.orientationLock = savedInstanceState.getInt(SAVED_ORIENTATION_LOCK, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
        }

        if(intent != null) {
            if (orientationLock == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
                // Only lock the orientation if it's not locked to something else yet
                boolean orientationLocked = intent.getBooleanExtra(Intents.Scan.ORIENTATION_LOCKED, true);

                if (orientationLocked) {
                    lockOrientation();
                }
            }

            if (Intents.Scan.ACTION.equals(intent.getAction())) {
                barcodeView.initializeFromIntent(intent);
            }

            if (!intent.getBooleanExtra(Intents.Scan.BEEP_ENABLED, true)) {
                beepManager.setBeepEnabled(false);
                beepManager.updatePrefs();
            }

            if (intent.hasExtra(Intents.Scan.TIMEOUT)) {
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        returnResultTimeout();
                    }
                };
                handler.postDelayed(runnable, intent.getLongExtra(Intents.Scan.TIMEOUT, 0L));
            }

            if (intent.getBooleanExtra(Intents.Scan.BARCODE_IMAGE_ENABLED, false)) {
                returnBarcodeImagePath = true;
            }
        }
    }

    /**
     * Lock display to current orientation.
     */
    protected void lockOrientation() {
        // Only get the orientation if it's not locked to one yet.
        if (this.orientationLock == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
            // Adapted from http://stackoverflow.com/a/14565436
            Display display = activity.getWindowManager().getDefaultDisplay();
            int rotation = display.getRotation();
            int baseOrientation = activity.getResources().getConfiguration().orientation;
            int orientation = 0;
            if (baseOrientation == Configuration.ORIENTATION_LANDSCAPE) {
                if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) {
                    orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
                } else {
                    orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
                }
            } else if (baseOrientation == Configuration.ORIENTATION_PORTRAIT) {
                if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_270) {
                    orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
                } else {
                    orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
                }
            }

            this.orientationLock = orientation;
        }
        //noinspection ResourceType
        activity.setRequestedOrientation(this.orientationLock);
    }

    /**
     * Start decoding.
     */
    public void decode() {
        barcodeView.decodeSingle(callback);
    }

    /**
     * Call from Activity#onResume().
     */
    public void onResume() {
        if(Build.VERSION.SDK_INT >= 23) {
            openCameraWithPermission();
        } else {
            barcodeView.resume();
        }
        beepManager.updatePrefs();
//        inactivityTimer.start();
    }

    private boolean askedPermission = false;

    @TargetApi(23)
    private void openCameraWithPermission() {
        if (ContextCompat.checkSelfPermission(this.activity, Manifest.permission.CAMERA)
                == PackageManager.PERMISSION_GRANTED) {
            barcodeView.resume();
        } else if(!askedPermission) {
            ActivityCompat.requestPermissions(this.activity,
                    new String[]{Manifest.permission.CAMERA},
                    cameraPermissionReqCode);
            askedPermission = true;
        } else {
            // Wait for permission result
        }
    }

    /**
     * Call from Activity#onRequestPermissionsResult
     * @param requestCode
     * @param permissions
     * @param grantResults
     */
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        if(requestCode == cameraPermissionReqCode) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // permission was granted
                barcodeView.resume();
            } else {
                // TODO: display better error message.
                displayFrameworkBugMessageAndExit();
            }
        }
    }


    /**
     * Call from Activity#onPause().
     */
    public void onPause() {
        barcodeView.pause();

//        inactivityTimer.cancel();
        beepManager.close();
    }

    /**
     * Call from Activity#onDestroy().
     */
    public void onDestroy() {
        destroyed = true;
//        inactivityTimer.cancel();
    }

    /**
     * Call from Activity#onSaveInstanceState().
     */
    public void onSaveInstanceState(Bundle outState) {
        outState.putInt(SAVED_ORIENTATION_LOCK, this.orientationLock);
    }


    /**
     * Create a intent to return as the Activity result.
     *
     * @param rawResult the BarcodeResult, must not be null.
     * @param barcodeImagePath a path to an exported file of the Barcode Image, can be null.
     * @return the Intent
     */
    public static Intent resultIntent(BarcodeResult rawResult, String barcodeImagePath) {
        Intent intent = new Intent(Intents.Scan.ACTION);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
        intent.putExtra(Intents.Scan.RESULT, rawResult.toString());
        intent.putExtra(Intents.Scan.RESULT_FORMAT, rawResult.getBarcodeFormat().toString());
        byte[] rawBytes = rawResult.getRawBytes();
        if (rawBytes != null && rawBytes.length > 0) {
            intent.putExtra(Intents.Scan.RESULT_BYTES, rawBytes);
        }
        Map metadata = rawResult.getResultMetadata();
        if (metadata != null) {
            if (metadata.containsKey(ResultMetadataType.UPC_EAN_EXTENSION)) {
                intent.putExtra(Intents.Scan.RESULT_UPC_EAN_EXTENSION,
                        metadata.get(ResultMetadataType.UPC_EAN_EXTENSION).toString());
            }
            Number orientation = (Number) metadata.get(ResultMetadataType.ORIENTATION);
            if (orientation != null) {
                intent.putExtra(Intents.Scan.RESULT_ORIENTATION, orientation.intValue());
            }
            String ecLevel = (String) metadata.get(ResultMetadataType.ERROR_CORRECTION_LEVEL);
            if (ecLevel != null) {
                intent.putExtra(Intents.Scan.RESULT_ERROR_CORRECTION_LEVEL, ecLevel);
            }
            @SuppressWarnings("unchecked")
            Iterable byteSegments = (Iterable) metadata.get(ResultMetadataType.BYTE_SEGMENTS);
            if (byteSegments != null) {
                int i = 0;
                for (byte[] byteSegment : byteSegments) {
                    intent.putExtra(Intents.Scan.RESULT_BYTE_SEGMENTS_PREFIX + i, byteSegment);
                    i++;
                }
            }
        }
        if (barcodeImagePath != null) {
            intent.putExtra(Intents.Scan.RESULT_BARCODE_IMAGE_PATH, barcodeImagePath);
        }
        return intent;
    }

    /**
     * Save the barcode image to a temporary file stored in the application's cache, and return its path.
     * Only does so if returnBarcodeImagePath is enabled.
     *
     * @param rawResult the BarcodeResult, must not be null
     * @return the path or null
     */
    private String getBarcodeImagePath(BarcodeResult rawResult) {
        String barcodeImagePath = null;
        if (returnBarcodeImagePath) {
            Bitmap bmp = rawResult.getBitmap();
            try {
                File bitmapFile = File.createTempFile("barcodeimage", ".jpg", activity.getCacheDir());
                FileOutputStream outputStream = new FileOutputStream(bitmapFile);
                bmp.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
                outputStream.close();
                barcodeImagePath = bitmapFile.getAbsolutePath();
            } catch (IOException e) {
                Log.w(TAG, "Unable to create temporary file and store bitmap! " + e);
            }
        }
        return barcodeImagePath;
    }

    private void finish() {
        activity.finish();
    }

    protected void returnResultTimeout() {
        Intent intent = new Intent(Intents.Scan.ACTION);
        intent.putExtra(Intents.Scan.TIMEOUT, true);
        activity.setResult(Activity.RESULT_CANCELED, intent);
        finish();
    }

    protected void returnResult(BarcodeResult rawResult) {
        if(scanningListener!=null){
            scanningListener.scanResult(rawResult.toString());
        }
//        Intent intent = resultIntent(rawResult, getBarcodeImagePath(rawResult));
//        activity.setResult(Activity.RESULT_OK, intent);
//        finish();
    }

    protected void displayFrameworkBugMessageAndExit() {
        if (activity.isFinishing() || this.destroyed) {
            return;
        }
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setTitle(activity.getString(com.google.zxing.client.android.R.string.zxing_app_name));
        builder.setMessage(activity.getString(com.google.zxing.client.android.R.string.zxing_msg_camera_framework_bug));
        builder.setPositiveButton(com.google.zxing.client.android.R.string.zxing_button_ok, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                finish();
            }
        });
        builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                finish();
            }
        });
        builder.show();
    }

    public static int getCameraPermissionReqCode() {
        return cameraPermissionReqCode;
    }

    public static void setCameraPermissionReqCode(int cameraPermissionReqCode) {
        CustomerCaptureManager.cameraPermissionReqCode = cameraPermissionReqCode;
    }

    public interface ScanningListener{
        void scanResult(String result);
    }
}
demo下载 https://download.csdn.net/download/a123473915/10437062

你可能感兴趣的:(Android zxing扫码,在预览页面持续扫描)