android - 想要在 Android 中使用 ZBar 扫描仪库进行更大的相机预览

标签 android android-camera zbar image-scanner

我在我的 Android 应用程序中使用 ZBarScannerActivity。但我在设备上看到的是一个小表面 View 。其实我想要全屏相机预览来扫描二维码。

如有任何帮助,我们将不胜感激。 谢谢。 这是 ZbarScanner Activity 的代码

package com.dm.zbar.android.scanner;


public class ZBarScannerActivity extends Activity implements Camera.PreviewCallback, ZBarConstants {

private static final String TAG = "ZBarScannerActivity";
private CameraPreview mPreview;
private Camera mCamera;
private ImageScanner mScanner;
private Handler mAutoFocusHandler;
private boolean mPreviewing = true;

static {
    System.loadLibrary("iconv");
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if(!isCameraAvailable()) {
        // Cancel request if there is no rear-facing camera.
        cancelRequest();
        return;
    }


    // Hide the window title.
    //requestWindowFeature(Window.FEATURE_NO_TITLE);
    //getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);


    mAutoFocusHandler = new Handler();

    // Create and configure the ImageScanner;
    setupScanner();

    // Create a RelativeLayout container that will hold a SurfaceView,
    // and set it as the content of our activity.
    mPreview = new CameraPreview(this, this, autoFocusCB);
    setContentView(mPreview);
}




public void setupScanner() {
    mScanner = new ImageScanner();
    mScanner.setConfig(0, Config.X_DENSITY, 3);
    mScanner.setConfig(0, Config.Y_DENSITY, 3);

    int[] symbols = getIntent().getIntArrayExtra(SCAN_MODES);
    if (symbols != null) {
        mScanner.setConfig(Symbol.NONE, Config.ENABLE, 0);
        for (int symbol : symbols) {
            mScanner.setConfig(symbol, Config.ENABLE, 1);
        }
    }
}

@Override
protected void onResume() {
    super.onResume();

    // Open the default i.e. the first rear facing camera.
    mCamera = Camera.open();
    if(mCamera == null) {
        // Cancel request if mCamera is null.
        cancelRequest();
        return;
    }

    mPreview.setCamera(mCamera);
    mPreview.showSurfaceView();

    mPreviewing = true;
}

@Override
protected void onPause() {
    super.onPause();

    // Because the Camera object is a shared resource, it's very
    // important to release it when the activity is paused.
    if (mCamera != null) {
        mPreview.setCamera(null);
        mCamera.cancelAutoFocus();
        mCamera.setPreviewCallback(null);
        mCamera.stopPreview();
        mCamera.release();

        // According to Jason Kuang on http://stackoverflow.com/questions/6519120/how-to-recover-camera-preview-from-sleep,
        // there might be surface recreation problems when the device goes to sleep. So lets just hide it and
        // recreate on resume
        mPreview.hideSurfaceView();

        mPreviewing = false;
        mCamera = null;
    }
}

public boolean isCameraAvailable() {
    PackageManager pm = getPackageManager();
    return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
}

public void cancelRequest() {
    Intent dataIntent = new Intent();
    dataIntent.putExtra(ERROR_INFO, "Camera unavailable.");
    setResult(Activity.RESULT_CANCELED, dataIntent);
    finish();
}

public void onPreviewFrame(byte[] data, Camera camera) {
    Camera.Parameters parameters = camera.getParameters();
    Camera.Size size = parameters.getPreviewSize();

    Image barcode = new Image(size.width, size.height, "Y800");
    barcode.setData(data);

    int result = mScanner.scanImage(barcode);

    if (result != 0) {
        mCamera.cancelAutoFocus();
        mCamera.setPreviewCallback(null);
        mCamera.stopPreview();
        mPreviewing = false;
        SymbolSet syms = mScanner.getResults();
        for (Symbol sym : syms) {
            String symData = sym.getData();
            if (!TextUtils.isEmpty(symData)) {
                Intent dataIntent = new Intent();
                dataIntent.putExtra(SCAN_RESULT, symData);
                dataIntent.putExtra(SCAN_RESULT_TYPE, sym.getType());
                setResult(Activity.RESULT_OK, dataIntent);
                finish();
                break;
            }
        }
    }
}
private Runnable doAutoFocus = new Runnable() {
    public void run() {
        if(mCamera != null && mPreviewing) {
            mCamera.autoFocus(autoFocusCB);
        }
    }
};

// Mimic continuous auto-focusing
Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
    public void onAutoFocus(boolean success, Camera camera) {
        mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
    }
};

和 CameraPreview 类 类 CameraPreview 扩展 ViewGroup 实现 SurfaceHolder.Callback { private final String TAG = "CameraPreview";

SurfaceView mSurfaceView;
SurfaceHolder mHolder;
Size mPreviewSize;
List<Size> mSupportedPreviewSizes;
Camera mCamera;
PreviewCallback mPreviewCallback;
AutoFocusCallback mAutoFocusCallback;

CameraPreview(Context context, PreviewCallback previewCallback, AutoFocusCallback autoFocusCb) {
    super(context);

    mPreviewCallback = previewCallback;
    mAutoFocusCallback = autoFocusCb;
    mSurfaceView = new SurfaceView(context);
    addView(mSurfaceView);

    // Install a SurfaceHolder.Callback so we get notified when the
    // underlying surface is created and destroyed.
    mHolder = mSurfaceView.getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public void setCamera(Camera camera) {
    mCamera = camera;
    if (mCamera != null) {
        //Changes********
        mCamera.setDisplayOrientation(90);
        mCamera.getParameters().getMaxNumFocusAreas();
        mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();

        requestLayout();
    }
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    // We purposely disregard child measurements because act as a
    // wrapper to a SurfaceView that centers the camera preview instead
    // of stretching it.



    final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
    final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
    setMeasuredDimension(width, height);

    if (mSupportedPreviewSizes != null) {
        mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
    }
}

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    if (changed && getChildCount() > 0) {
        final View child = getChildAt(0);


        final int width = r - l;
        final int height = b - t;

        int previewWidth = width;
        int previewHeight = height;
        if (mPreviewSize != null) {
            previewWidth = mPreviewSize.width;
            previewHeight = mPreviewSize.height;
        }

        // Center the child SurfaceView within the parent.
        if (width * previewHeight > height * previewWidth) {
            final int scaledChildWidth = previewWidth * height / previewHeight;
            child.layout((width - scaledChildWidth) / 2, 0,
                    (width + scaledChildWidth) / 2, height);
        } else {
            final int scaledChildHeight = previewHeight * width / previewWidth;
            child.layout(0, (height - scaledChildHeight) / 2,
                    width, (height + scaledChildHeight) / 2);
        }
    }
}

public void hideSurfaceView() {
    mSurfaceView.setVisibility(View.INVISIBLE);
}

public void showSurfaceView() {
    mSurfaceView.setVisibility(View.VISIBLE);
}

public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, acquire the camera and tell it where
    // to draw.
    try {
        if (mCamera != null) {
            mCamera.setPreviewDisplay(holder);
        }
    } catch (IOException exception) {
        Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    // Surface will be destroyed when we return, so stop the preview.
    if (mCamera != null) {
        mCamera.cancelAutoFocus();
        mCamera.stopPreview();
    }
}


private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio = (double) w / h;
    if (sizes == null) return null;

    Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;

    // Try to find an size match aspect ratio and size

    for (Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }

    // Cannot find the one match the aspect ratio, ignore the requirement
    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    if (holder.getSurface() == null){
      // preview surface does not exist
      return;
    }

    if (mCamera != null) {
        // Now that the size is known, set up the camera parameters and begin
        // the preview.
        Camera.Parameters parameters = mCamera.getParameters();
        parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
        requestLayout();

       // mCamera.setDisplayOrientation(90);
        mCamera.setParameters(parameters);
        mCamera.setPreviewCallback(mPreviewCallback);
        mCamera.startPreview();
        mCamera.autoFocus(mAutoFocusCallback);
    }
}

请帮我获取相机预览大小的场景。

最佳答案

I am getting a small surface view on device. Actually I want full Screen camera preview to scan the QR code

  • 如果您说相机没有占据整个屏幕,那么请尝试更改

    android:layout_width="match_parent"
    android:layout_height="match_parent"
    

SurfaceViewparent_layout

  • 如果它是关于您想要全屏显示的扫描区域,那么它是:

    mScannerView = new ZBarScannerView(this) {
            /**
             * this will alter the scanning area
             **/
            @Override
            protected IViewFinder createViewFinderView(Context context) {
                return new CustomViewFinderView(context);
            } 
        };
    
    
    
    private class CustomViewFinderView extends ViewFinderView {
        Context context;
    
        public CustomViewFinderView(Context context) {
            super(context);
            this.context = context;
            setLaserEnabled(true);
        }
    
        @Override
        public void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (getFramingRect() != null) {
                updateFrameRect();
                setBorderColor(ContextCompat.getColor(context, R.color.colorPrimary));
            }
        }
    
        private void updateFrameRect() {
            Point viewResolution = new Point(this.getWidth(), this.getHeight());
            int height = (int) ((float) this.getHeight());
            int width = (int) ((float) this.getWidth());
    
            int leftOffset = (viewResolution.x - width) / 2;
            int topOffset = (viewResolution.y - height) / 2;
    
            getFramingRect().left = leftOffset;
            getFramingRect().top = topOffset;
            getFramingRect().right = leftOffset + width;
            getFramingRect().bottom = topOffset + height;
        }
    }
    

结果:

enter image description here

关于android - 想要在 Android 中使用 ZBar 扫描仪库进行更大的相机预览,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37437183/

相关文章:

android - 在 Android 上的 RxJava2 中结合 Singles 的最佳方式?

android - 滚动 ProgressBars 的 ListView

java - 尝试在空对象引用上调用虚拟方法 'android.view.SurfaceHolder android.view.SurfaceView.getHolder()'

javascript - 条形码扫描器 react native android UI 组件未显示

android - Gradle 构建 : Execution failed for task ':app:lint'

android - 实现横向导航时应用程序崩溃

android - 相机预览在三星 Galaxy Grand 中模糊,但在三星 S3 中很好

java - Android 保存的图像质量低

ios - 在 iPhone 5s 64 位上运行 32 位库

objective-c - 在 UIView 中实现 ZBar 二维码阅读器