Import source from https://github.com/dm77/barcodescanner
This commit is contained in:
parent
69680a9856
commit
e9f9decf00
|
@ -239,7 +239,6 @@ ext.groups = [
|
||||||
regex: [
|
regex: [
|
||||||
],
|
],
|
||||||
group: [
|
group: [
|
||||||
'me.dm7.barcodescanner',
|
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace "me.dm7.barcodescanner.core"
|
||||||
|
compileSdk versions.compileSdk
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk versions.minSdk
|
||||||
|
targetSdk versions.targetSdk
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility versions.sourceCompat
|
||||||
|
targetCompatibility versions.targetCompat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'androidx.annotation:annotation-jvm:1.6.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
tasks.findAll { it.name.startsWith("lint") }.each {
|
||||||
|
it.enabled = false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,339 @@
|
||||||
|
package me.dm7.barcodescanner.core;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.hardware.Camera;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
|
||||||
|
public abstract class BarcodeScannerView extends FrameLayout implements Camera.PreviewCallback {
|
||||||
|
|
||||||
|
private CameraWrapper mCameraWrapper;
|
||||||
|
private CameraPreview mPreview;
|
||||||
|
private IViewFinder mViewFinderView;
|
||||||
|
private Rect mFramingRectInPreview;
|
||||||
|
private CameraHandlerThread mCameraHandlerThread;
|
||||||
|
private Boolean mFlashState;
|
||||||
|
private boolean mAutofocusState = true;
|
||||||
|
private boolean mShouldScaleToFill = true;
|
||||||
|
|
||||||
|
private boolean mIsLaserEnabled = true;
|
||||||
|
@ColorInt private int mLaserColor = getResources().getColor(R.color.viewfinder_laser);
|
||||||
|
@ColorInt private int mBorderColor = getResources().getColor(R.color.viewfinder_border);
|
||||||
|
private int mMaskColor = getResources().getColor(R.color.viewfinder_mask);
|
||||||
|
private int mBorderWidth = getResources().getInteger(R.integer.viewfinder_border_width);
|
||||||
|
private int mBorderLength = getResources().getInteger(R.integer.viewfinder_border_length);
|
||||||
|
private boolean mRoundedCorner = false;
|
||||||
|
private int mCornerRadius = 0;
|
||||||
|
private boolean mSquaredFinder = false;
|
||||||
|
private float mBorderAlpha = 1.0f;
|
||||||
|
private int mViewFinderOffset = 0;
|
||||||
|
private float mAspectTolerance = 0.1f;
|
||||||
|
|
||||||
|
public BarcodeScannerView(Context context) {
|
||||||
|
super(context);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BarcodeScannerView(Context context, AttributeSet attributeSet) {
|
||||||
|
super(context, attributeSet);
|
||||||
|
|
||||||
|
TypedArray a = context.getTheme().obtainStyledAttributes(
|
||||||
|
attributeSet,
|
||||||
|
R.styleable.BarcodeScannerView,
|
||||||
|
0, 0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
setShouldScaleToFill(a.getBoolean(R.styleable.BarcodeScannerView_shouldScaleToFill, true));
|
||||||
|
mIsLaserEnabled = a.getBoolean(R.styleable.BarcodeScannerView_laserEnabled, mIsLaserEnabled);
|
||||||
|
mLaserColor = a.getColor(R.styleable.BarcodeScannerView_laserColor, mLaserColor);
|
||||||
|
mBorderColor = a.getColor(R.styleable.BarcodeScannerView_borderColor, mBorderColor);
|
||||||
|
mMaskColor = a.getColor(R.styleable.BarcodeScannerView_maskColor, mMaskColor);
|
||||||
|
mBorderWidth = a.getDimensionPixelSize(R.styleable.BarcodeScannerView_borderWidth, mBorderWidth);
|
||||||
|
mBorderLength = a.getDimensionPixelSize(R.styleable.BarcodeScannerView_borderLength, mBorderLength);
|
||||||
|
|
||||||
|
mRoundedCorner = a.getBoolean(R.styleable.BarcodeScannerView_roundedCorner, mRoundedCorner);
|
||||||
|
mCornerRadius = a.getDimensionPixelSize(R.styleable.BarcodeScannerView_cornerRadius, mCornerRadius);
|
||||||
|
mSquaredFinder = a.getBoolean(R.styleable.BarcodeScannerView_squaredFinder, mSquaredFinder);
|
||||||
|
mBorderAlpha = a.getFloat(R.styleable.BarcodeScannerView_borderAlpha, mBorderAlpha);
|
||||||
|
mViewFinderOffset = a.getDimensionPixelSize(R.styleable.BarcodeScannerView_finderOffset, mViewFinderOffset);
|
||||||
|
} finally {
|
||||||
|
a.recycle();
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
mViewFinderView = createViewFinderView(getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setupLayout(CameraWrapper cameraWrapper) {
|
||||||
|
removeAllViews();
|
||||||
|
|
||||||
|
mPreview = new CameraPreview(getContext(), cameraWrapper, this);
|
||||||
|
mPreview.setAspectTolerance(mAspectTolerance);
|
||||||
|
mPreview.setShouldScaleToFill(mShouldScaleToFill);
|
||||||
|
if (!mShouldScaleToFill) {
|
||||||
|
RelativeLayout relativeLayout = new RelativeLayout(getContext());
|
||||||
|
relativeLayout.setGravity(Gravity.CENTER);
|
||||||
|
relativeLayout.setBackgroundColor(Color.BLACK);
|
||||||
|
relativeLayout.addView(mPreview);
|
||||||
|
addView(relativeLayout);
|
||||||
|
} else {
|
||||||
|
addView(mPreview);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mViewFinderView instanceof View) {
|
||||||
|
addView((View) mViewFinderView);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("IViewFinder object returned by " +
|
||||||
|
"'createViewFinderView()' should be instance of android.view.View");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Method that creates view that represents visual appearance of a barcode scanner</p>
|
||||||
|
* <p>Override it to provide your own view for visual appearance of a barcode scanner</p>
|
||||||
|
*
|
||||||
|
* @param context {@link Context}
|
||||||
|
* @return {@link android.view.View} that implements {@link ViewFinderView}
|
||||||
|
*/
|
||||||
|
protected IViewFinder createViewFinderView(Context context) {
|
||||||
|
ViewFinderView viewFinderView = new ViewFinderView(context);
|
||||||
|
viewFinderView.setBorderColor(mBorderColor);
|
||||||
|
viewFinderView.setLaserColor(mLaserColor);
|
||||||
|
viewFinderView.setLaserEnabled(mIsLaserEnabled);
|
||||||
|
viewFinderView.setBorderStrokeWidth(mBorderWidth);
|
||||||
|
viewFinderView.setBorderLineLength(mBorderLength);
|
||||||
|
viewFinderView.setMaskColor(mMaskColor);
|
||||||
|
|
||||||
|
viewFinderView.setBorderCornerRounded(mRoundedCorner);
|
||||||
|
viewFinderView.setBorderCornerRadius(mCornerRadius);
|
||||||
|
viewFinderView.setSquareViewFinder(mSquaredFinder);
|
||||||
|
viewFinderView.setViewFinderOffset(mViewFinderOffset);
|
||||||
|
return viewFinderView;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLaserColor(int laserColor) {
|
||||||
|
mLaserColor = laserColor;
|
||||||
|
mViewFinderView.setLaserColor(mLaserColor);
|
||||||
|
mViewFinderView.setupViewFinder();
|
||||||
|
}
|
||||||
|
public void setMaskColor(int maskColor) {
|
||||||
|
mMaskColor = maskColor;
|
||||||
|
mViewFinderView.setMaskColor(mMaskColor);
|
||||||
|
mViewFinderView.setupViewFinder();
|
||||||
|
}
|
||||||
|
public void setBorderColor(int borderColor) {
|
||||||
|
mBorderColor = borderColor;
|
||||||
|
mViewFinderView.setBorderColor(mBorderColor);
|
||||||
|
mViewFinderView.setupViewFinder();
|
||||||
|
}
|
||||||
|
public void setBorderStrokeWidth(int borderStrokeWidth) {
|
||||||
|
mBorderWidth = borderStrokeWidth;
|
||||||
|
mViewFinderView.setBorderStrokeWidth(mBorderWidth);
|
||||||
|
mViewFinderView.setupViewFinder();
|
||||||
|
}
|
||||||
|
public void setBorderLineLength(int borderLineLength) {
|
||||||
|
mBorderLength = borderLineLength;
|
||||||
|
mViewFinderView.setBorderLineLength(mBorderLength);
|
||||||
|
mViewFinderView.setupViewFinder();
|
||||||
|
}
|
||||||
|
public void setLaserEnabled(boolean isLaserEnabled) {
|
||||||
|
mIsLaserEnabled = isLaserEnabled;
|
||||||
|
mViewFinderView.setLaserEnabled(mIsLaserEnabled);
|
||||||
|
mViewFinderView.setupViewFinder();
|
||||||
|
}
|
||||||
|
public void setIsBorderCornerRounded(boolean isBorderCornerRounded) {
|
||||||
|
mRoundedCorner = isBorderCornerRounded;
|
||||||
|
mViewFinderView.setBorderCornerRounded(mRoundedCorner);
|
||||||
|
mViewFinderView.setupViewFinder();
|
||||||
|
}
|
||||||
|
public void setBorderCornerRadius(int borderCornerRadius) {
|
||||||
|
mCornerRadius = borderCornerRadius;
|
||||||
|
mViewFinderView.setBorderCornerRadius(mCornerRadius);
|
||||||
|
mViewFinderView.setupViewFinder();
|
||||||
|
}
|
||||||
|
public void setSquareViewFinder(boolean isSquareViewFinder) {
|
||||||
|
mSquaredFinder = isSquareViewFinder;
|
||||||
|
mViewFinderView.setSquareViewFinder(mSquaredFinder);
|
||||||
|
mViewFinderView.setupViewFinder();
|
||||||
|
}
|
||||||
|
public void setBorderAlpha(float borderAlpha) {
|
||||||
|
mBorderAlpha = borderAlpha;
|
||||||
|
mViewFinderView.setBorderAlpha(mBorderAlpha);
|
||||||
|
mViewFinderView.setupViewFinder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startCamera(int cameraId) {
|
||||||
|
if(mCameraHandlerThread == null) {
|
||||||
|
mCameraHandlerThread = new CameraHandlerThread(this);
|
||||||
|
}
|
||||||
|
mCameraHandlerThread.startCamera(cameraId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupCameraPreview(CameraWrapper cameraWrapper) {
|
||||||
|
mCameraWrapper = cameraWrapper;
|
||||||
|
if(mCameraWrapper != null) {
|
||||||
|
setupLayout(mCameraWrapper);
|
||||||
|
mViewFinderView.setupViewFinder();
|
||||||
|
if(mFlashState != null) {
|
||||||
|
setFlash(mFlashState);
|
||||||
|
}
|
||||||
|
setAutoFocus(mAutofocusState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startCamera() {
|
||||||
|
startCamera(CameraUtils.getDefaultCameraId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopCamera() {
|
||||||
|
if(mCameraWrapper != null) {
|
||||||
|
mPreview.stopCameraPreview();
|
||||||
|
mPreview.setCamera(null, null);
|
||||||
|
mCameraWrapper.mCamera.release();
|
||||||
|
mCameraWrapper = null;
|
||||||
|
}
|
||||||
|
if(mCameraHandlerThread != null) {
|
||||||
|
mCameraHandlerThread.quit();
|
||||||
|
mCameraHandlerThread = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopCameraPreview() {
|
||||||
|
if(mPreview != null) {
|
||||||
|
mPreview.stopCameraPreview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void resumeCameraPreview() {
|
||||||
|
if(mPreview != null) {
|
||||||
|
mPreview.showCameraPreview();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Rect getFramingRectInPreview(int previewWidth, int previewHeight) {
|
||||||
|
if (mFramingRectInPreview == null) {
|
||||||
|
Rect framingRect = mViewFinderView.getFramingRect();
|
||||||
|
int viewFinderViewWidth = mViewFinderView.getWidth();
|
||||||
|
int viewFinderViewHeight = mViewFinderView.getHeight();
|
||||||
|
if (framingRect == null || viewFinderViewWidth == 0 || viewFinderViewHeight == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect rect = new Rect(framingRect);
|
||||||
|
|
||||||
|
if(previewWidth < viewFinderViewWidth) {
|
||||||
|
rect.left = rect.left * previewWidth / viewFinderViewWidth;
|
||||||
|
rect.right = rect.right * previewWidth / viewFinderViewWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(previewHeight < viewFinderViewHeight) {
|
||||||
|
rect.top = rect.top * previewHeight / viewFinderViewHeight;
|
||||||
|
rect.bottom = rect.bottom * previewHeight / viewFinderViewHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
mFramingRectInPreview = rect;
|
||||||
|
}
|
||||||
|
return mFramingRectInPreview;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlash(boolean flag) {
|
||||||
|
mFlashState = flag;
|
||||||
|
if(mCameraWrapper != null && CameraUtils.isFlashSupported(mCameraWrapper.mCamera)) {
|
||||||
|
|
||||||
|
Camera.Parameters parameters = mCameraWrapper.mCamera.getParameters();
|
||||||
|
if(flag) {
|
||||||
|
if(parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_TORCH)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
|
||||||
|
} else {
|
||||||
|
if(parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_OFF)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
|
||||||
|
}
|
||||||
|
mCameraWrapper.mCamera.setParameters(parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getFlash() {
|
||||||
|
if(mCameraWrapper != null && CameraUtils.isFlashSupported(mCameraWrapper.mCamera)) {
|
||||||
|
Camera.Parameters parameters = mCameraWrapper.mCamera.getParameters();
|
||||||
|
if(parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_TORCH)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggleFlash() {
|
||||||
|
if(mCameraWrapper != null && CameraUtils.isFlashSupported(mCameraWrapper.mCamera)) {
|
||||||
|
Camera.Parameters parameters = mCameraWrapper.mCamera.getParameters();
|
||||||
|
if(parameters.getFlashMode().equals(Camera.Parameters.FLASH_MODE_TORCH)) {
|
||||||
|
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
|
||||||
|
} else {
|
||||||
|
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
|
||||||
|
}
|
||||||
|
mCameraWrapper.mCamera.setParameters(parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoFocus(boolean state) {
|
||||||
|
mAutofocusState = state;
|
||||||
|
if(mPreview != null) {
|
||||||
|
mPreview.setAutoFocus(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShouldScaleToFill(boolean shouldScaleToFill) {
|
||||||
|
mShouldScaleToFill = shouldScaleToFill;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAspectTolerance(float aspectTolerance) {
|
||||||
|
mAspectTolerance = aspectTolerance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getRotatedData(byte[] data, Camera camera) {
|
||||||
|
Camera.Parameters parameters = camera.getParameters();
|
||||||
|
Camera.Size size = parameters.getPreviewSize();
|
||||||
|
int width = size.width;
|
||||||
|
int height = size.height;
|
||||||
|
|
||||||
|
int rotationCount = getRotationCount();
|
||||||
|
|
||||||
|
if(rotationCount == 1 || rotationCount == 3) {
|
||||||
|
for (int i = 0; i < rotationCount; i++) {
|
||||||
|
byte[] rotatedData = new byte[data.length];
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int x = 0; x < width; x++)
|
||||||
|
rotatedData[x * height + height - y - 1] = data[x + y * width];
|
||||||
|
}
|
||||||
|
data = rotatedData;
|
||||||
|
int tmp = width;
|
||||||
|
width = height;
|
||||||
|
height = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRotationCount() {
|
||||||
|
int displayOrientation = mPreview.getDisplayOrientation();
|
||||||
|
return displayOrientation / 90;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package me.dm7.barcodescanner.core;
|
||||||
|
|
||||||
|
|
||||||
|
import android.hardware.Camera;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
// This code is mostly based on the top answer here: http://stackoverflow.com/questions/18149964/best-use-of-handlerthread-over-other-similar-classes
|
||||||
|
public class CameraHandlerThread extends HandlerThread {
|
||||||
|
private static final String LOG_TAG = "CameraHandlerThread";
|
||||||
|
|
||||||
|
private BarcodeScannerView mScannerView;
|
||||||
|
|
||||||
|
public CameraHandlerThread(BarcodeScannerView scannerView) {
|
||||||
|
super("CameraHandlerThread");
|
||||||
|
mScannerView = scannerView;
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startCamera(final int cameraId) {
|
||||||
|
Handler localHandler = new Handler(getLooper());
|
||||||
|
localHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
final Camera camera = CameraUtils.getCameraInstance(cameraId);
|
||||||
|
Handler mainHandler = new Handler(Looper.getMainLooper());
|
||||||
|
mainHandler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
mScannerView.setupCameraPreview(CameraWrapper.getWrapper(camera, cameraId));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
312
library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraPreview.java
vendored
Normal file
312
library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraPreview.java
vendored
Normal file
|
@ -0,0 +1,312 @@
|
||||||
|
package me.dm7.barcodescanner.core;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.hardware.Camera;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Display;
|
||||||
|
import android.view.Surface;
|
||||||
|
import android.view.SurfaceHolder;
|
||||||
|
import android.view.SurfaceView;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
|
||||||
|
private static final String TAG = "CameraPreview";
|
||||||
|
|
||||||
|
private CameraWrapper mCameraWrapper;
|
||||||
|
private Handler mAutoFocusHandler;
|
||||||
|
private boolean mPreviewing = true;
|
||||||
|
private boolean mAutoFocus = true;
|
||||||
|
private boolean mSurfaceCreated = false;
|
||||||
|
private boolean mShouldScaleToFill = true;
|
||||||
|
private Camera.PreviewCallback mPreviewCallback;
|
||||||
|
private float mAspectTolerance = 0.1f;
|
||||||
|
|
||||||
|
public CameraPreview(Context context, CameraWrapper cameraWrapper, Camera.PreviewCallback previewCallback) {
|
||||||
|
super(context);
|
||||||
|
init(cameraWrapper, previewCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CameraPreview(Context context, AttributeSet attrs, CameraWrapper cameraWrapper, Camera.PreviewCallback previewCallback) {
|
||||||
|
super(context, attrs);
|
||||||
|
init(cameraWrapper, previewCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init(CameraWrapper cameraWrapper, Camera.PreviewCallback previewCallback) {
|
||||||
|
setCamera(cameraWrapper, previewCallback);
|
||||||
|
mAutoFocusHandler = new Handler();
|
||||||
|
getHolder().addCallback(this);
|
||||||
|
getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCamera(CameraWrapper cameraWrapper, Camera.PreviewCallback previewCallback) {
|
||||||
|
mCameraWrapper = cameraWrapper;
|
||||||
|
mPreviewCallback = previewCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setShouldScaleToFill(boolean scaleToFill) {
|
||||||
|
mShouldScaleToFill = scaleToFill;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAspectTolerance(float aspectTolerance) {
|
||||||
|
mAspectTolerance = aspectTolerance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void surfaceCreated(SurfaceHolder surfaceHolder) {
|
||||||
|
mSurfaceCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i2, int i3) {
|
||||||
|
if(surfaceHolder.getSurface() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stopCameraPreview();
|
||||||
|
showCameraPreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
|
||||||
|
mSurfaceCreated = false;
|
||||||
|
stopCameraPreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showCameraPreview() {
|
||||||
|
if(mCameraWrapper != null) {
|
||||||
|
try {
|
||||||
|
getHolder().addCallback(this);
|
||||||
|
mPreviewing = true;
|
||||||
|
setupCameraParameters();
|
||||||
|
mCameraWrapper.mCamera.setPreviewDisplay(getHolder());
|
||||||
|
mCameraWrapper.mCamera.setDisplayOrientation(getDisplayOrientation());
|
||||||
|
mCameraWrapper.mCamera.setOneShotPreviewCallback(mPreviewCallback);
|
||||||
|
mCameraWrapper.mCamera.startPreview();
|
||||||
|
if(mAutoFocus) {
|
||||||
|
if (mSurfaceCreated) { // check if surface created before using autofocus
|
||||||
|
safeAutoFocus();
|
||||||
|
} else {
|
||||||
|
scheduleAutoFocus(); // wait 1 sec and then do check again
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void safeAutoFocus() {
|
||||||
|
try {
|
||||||
|
mCameraWrapper.mCamera.autoFocus(autoFocusCB);
|
||||||
|
} catch (RuntimeException re) {
|
||||||
|
// Horrible hack to deal with autofocus errors on Sony devices
|
||||||
|
// See https://github.com/dm77/barcodescanner/issues/7 for example
|
||||||
|
scheduleAutoFocus(); // wait 1 sec and then do check again
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopCameraPreview() {
|
||||||
|
if(mCameraWrapper != null) {
|
||||||
|
try {
|
||||||
|
mPreviewing = false;
|
||||||
|
getHolder().removeCallback(this);
|
||||||
|
mCameraWrapper.mCamera.cancelAutoFocus();
|
||||||
|
mCameraWrapper.mCamera.setOneShotPreviewCallback(null);
|
||||||
|
mCameraWrapper.mCamera.stopPreview();
|
||||||
|
} catch(Exception e) {
|
||||||
|
Log.e(TAG, e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupCameraParameters() {
|
||||||
|
Camera.Size optimalSize = getOptimalPreviewSize();
|
||||||
|
Camera.Parameters parameters = mCameraWrapper.mCamera.getParameters();
|
||||||
|
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
|
||||||
|
mCameraWrapper.mCamera.setParameters(parameters);
|
||||||
|
adjustViewSize(optimalSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void adjustViewSize(Camera.Size cameraSize) {
|
||||||
|
Point previewSize = convertSizeToLandscapeOrientation(new Point(getWidth(), getHeight()));
|
||||||
|
float cameraRatio = ((float) cameraSize.width) / cameraSize.height;
|
||||||
|
float screenRatio = ((float) previewSize.x) / previewSize.y;
|
||||||
|
|
||||||
|
if (screenRatio > cameraRatio) {
|
||||||
|
setViewSize((int) (previewSize.y * cameraRatio), previewSize.y);
|
||||||
|
} else {
|
||||||
|
setViewSize(previewSize.x, (int) (previewSize.x / cameraRatio));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("SuspiciousNameCombination")
|
||||||
|
private Point convertSizeToLandscapeOrientation(Point size) {
|
||||||
|
if (getDisplayOrientation() % 180 == 0) {
|
||||||
|
return size;
|
||||||
|
} else {
|
||||||
|
return new Point(size.y, size.x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("SuspiciousNameCombination")
|
||||||
|
private void setViewSize(int width, int height) {
|
||||||
|
ViewGroup.LayoutParams layoutParams = getLayoutParams();
|
||||||
|
int tmpWidth;
|
||||||
|
int tmpHeight;
|
||||||
|
if (getDisplayOrientation() % 180 == 0) {
|
||||||
|
tmpWidth = width;
|
||||||
|
tmpHeight = height;
|
||||||
|
} else {
|
||||||
|
tmpWidth = height;
|
||||||
|
tmpHeight = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mShouldScaleToFill) {
|
||||||
|
int parentWidth = ((View) getParent()).getWidth();
|
||||||
|
int parentHeight = ((View) getParent()).getHeight();
|
||||||
|
float ratioWidth = (float) parentWidth / (float) tmpWidth;
|
||||||
|
float ratioHeight = (float) parentHeight / (float) tmpHeight;
|
||||||
|
|
||||||
|
float compensation;
|
||||||
|
|
||||||
|
if (ratioWidth > ratioHeight) {
|
||||||
|
compensation = ratioWidth;
|
||||||
|
} else {
|
||||||
|
compensation = ratioHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpWidth = Math.round(tmpWidth * compensation);
|
||||||
|
tmpHeight = Math.round(tmpHeight * compensation);
|
||||||
|
}
|
||||||
|
|
||||||
|
layoutParams.width = tmpWidth;
|
||||||
|
layoutParams.height = tmpHeight;
|
||||||
|
setLayoutParams(layoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDisplayOrientation() {
|
||||||
|
if (mCameraWrapper == null) {
|
||||||
|
//If we don't have a camera set there is no orientation so return dummy value
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Camera.CameraInfo info = new Camera.CameraInfo();
|
||||||
|
if(mCameraWrapper.mCameraId == -1) {
|
||||||
|
Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
|
||||||
|
} else {
|
||||||
|
Camera.getCameraInfo(mCameraWrapper.mCameraId, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
Display display = wm.getDefaultDisplay();
|
||||||
|
|
||||||
|
int rotation = display.getRotation();
|
||||||
|
int degrees = 0;
|
||||||
|
switch (rotation) {
|
||||||
|
case Surface.ROTATION_0: degrees = 0; break;
|
||||||
|
case Surface.ROTATION_90: degrees = 90; break;
|
||||||
|
case Surface.ROTATION_180: degrees = 180; break;
|
||||||
|
case Surface.ROTATION_270: degrees = 270; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result;
|
||||||
|
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
||||||
|
result = (info.orientation + degrees) % 360;
|
||||||
|
result = (360 - result) % 360; // compensate the mirror
|
||||||
|
} else { // back-facing
|
||||||
|
result = (info.orientation - degrees + 360) % 360;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Camera.Size getOptimalPreviewSize() {
|
||||||
|
if(mCameraWrapper == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Camera.Size> sizes = mCameraWrapper.mCamera.getParameters().getSupportedPreviewSizes();
|
||||||
|
int w = getWidth();
|
||||||
|
int h = getHeight();
|
||||||
|
if (DisplayUtils.getScreenOrientation(getContext()) == Configuration.ORIENTATION_PORTRAIT) {
|
||||||
|
int portraitWidth = h;
|
||||||
|
h = w;
|
||||||
|
w = portraitWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
double targetRatio = (double) w / h;
|
||||||
|
if (sizes == null) return null;
|
||||||
|
|
||||||
|
Camera.Size optimalSize = null;
|
||||||
|
double minDiff = Double.MAX_VALUE;
|
||||||
|
|
||||||
|
int targetHeight = h;
|
||||||
|
|
||||||
|
// Try to find an size match aspect ratio and size
|
||||||
|
for (Camera.Size size : sizes) {
|
||||||
|
double ratio = (double) size.width / size.height;
|
||||||
|
if (Math.abs(ratio - targetRatio) > mAspectTolerance) 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 (Camera.Size size : sizes) {
|
||||||
|
if (Math.abs(size.height - targetHeight) < minDiff) {
|
||||||
|
optimalSize = size;
|
||||||
|
minDiff = Math.abs(size.height - targetHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return optimalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutoFocus(boolean state) {
|
||||||
|
if(mCameraWrapper != null && mPreviewing) {
|
||||||
|
if(state == mAutoFocus) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mAutoFocus = state;
|
||||||
|
if(mAutoFocus) {
|
||||||
|
if (mSurfaceCreated) { // check if surface created before using autofocus
|
||||||
|
Log.v(TAG, "Starting autofocus");
|
||||||
|
safeAutoFocus();
|
||||||
|
} else {
|
||||||
|
scheduleAutoFocus(); // wait 1 sec and then do check again
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.v(TAG, "Cancelling autofocus");
|
||||||
|
mCameraWrapper.mCamera.cancelAutoFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Runnable doAutoFocus = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if(mCameraWrapper != null && mPreviewing && mAutoFocus && mSurfaceCreated) {
|
||||||
|
safeAutoFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mimic continuous auto-focusing
|
||||||
|
Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
|
||||||
|
public void onAutoFocus(boolean success, Camera camera) {
|
||||||
|
scheduleAutoFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private void scheduleAutoFocus() {
|
||||||
|
mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
|
||||||
|
}
|
||||||
|
}
|
63
library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraUtils.java
vendored
Normal file
63
library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraUtils.java
vendored
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
package me.dm7.barcodescanner.core;
|
||||||
|
|
||||||
|
import android.hardware.Camera;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CameraUtils {
|
||||||
|
/** A safe way to get an instance of the Camera object. */
|
||||||
|
public static Camera getCameraInstance() {
|
||||||
|
return getCameraInstance(getDefaultCameraId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Favor back-facing camera by default. If none exists, fallback to whatever camera is available **/
|
||||||
|
public static int getDefaultCameraId() {
|
||||||
|
int numberOfCameras = Camera.getNumberOfCameras();
|
||||||
|
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
|
||||||
|
int defaultCameraId = -1;
|
||||||
|
for (int i = 0; i < numberOfCameras; i++) {
|
||||||
|
defaultCameraId = i;
|
||||||
|
Camera.getCameraInfo(i, cameraInfo);
|
||||||
|
if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultCameraId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A safe way to get an instance of the Camera object. */
|
||||||
|
public static Camera getCameraInstance(int cameraId) {
|
||||||
|
Camera c = null;
|
||||||
|
try {
|
||||||
|
if(cameraId == -1) {
|
||||||
|
c = Camera.open(); // attempt to get a Camera instance
|
||||||
|
} else {
|
||||||
|
c = Camera.open(cameraId); // attempt to get a Camera instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
// Camera is not available (in use or does not exist)
|
||||||
|
}
|
||||||
|
return c; // returns null if camera is unavailable
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isFlashSupported(Camera camera) {
|
||||||
|
/* Credits: Top answer at http://stackoverflow.com/a/19599365/868173 */
|
||||||
|
if (camera != null) {
|
||||||
|
Camera.Parameters parameters = camera.getParameters();
|
||||||
|
|
||||||
|
if (parameters.getFlashMode() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> supportedFlashModes = parameters.getSupportedFlashModes();
|
||||||
|
if (supportedFlashModes == null || supportedFlashModes.isEmpty() || supportedFlashModes.size() == 1 && supportedFlashModes.get(0).equals(Camera.Parameters.FLASH_MODE_OFF)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
23
library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraWrapper.java
vendored
Normal file
23
library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/CameraWrapper.java
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
package me.dm7.barcodescanner.core;
|
||||||
|
|
||||||
|
import android.hardware.Camera;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public class CameraWrapper {
|
||||||
|
public final Camera mCamera;
|
||||||
|
public final int mCameraId;
|
||||||
|
|
||||||
|
private CameraWrapper(@NonNull Camera camera, int cameraId) {
|
||||||
|
this.mCamera = camera;
|
||||||
|
this.mCameraId = cameraId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CameraWrapper getWrapper(Camera camera, int cameraId) {
|
||||||
|
if (camera == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return new CameraWrapper(camera, cameraId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/DisplayUtils.java
vendored
Normal file
41
library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/DisplayUtils.java
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package me.dm7.barcodescanner.core;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.view.Display;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
public class DisplayUtils {
|
||||||
|
public static Point getScreenResolution(Context context) {
|
||||||
|
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
Display display = wm.getDefaultDisplay();
|
||||||
|
Point screenResolution = new Point();
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= 13) {
|
||||||
|
display.getSize(screenResolution);
|
||||||
|
} else {
|
||||||
|
screenResolution.set(display.getWidth(), display.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
return screenResolution;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getScreenOrientation(Context context)
|
||||||
|
{
|
||||||
|
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
|
||||||
|
Display display = wm.getDefaultDisplay();
|
||||||
|
|
||||||
|
int orientation = Configuration.ORIENTATION_UNDEFINED;
|
||||||
|
if(display.getWidth()==display.getHeight()){
|
||||||
|
orientation = Configuration.ORIENTATION_SQUARE;
|
||||||
|
} else{
|
||||||
|
if(display.getWidth() < display.getHeight()){
|
||||||
|
orientation = Configuration.ORIENTATION_PORTRAIT;
|
||||||
|
}else {
|
||||||
|
orientation = Configuration.ORIENTATION_LANDSCAPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
53
library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/IViewFinder.java
vendored
Normal file
53
library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/IViewFinder.java
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
package me.dm7.barcodescanner.core;
|
||||||
|
|
||||||
|
import android.graphics.Rect;
|
||||||
|
|
||||||
|
public interface IViewFinder {
|
||||||
|
|
||||||
|
void setLaserColor(int laserColor);
|
||||||
|
void setMaskColor(int maskColor);
|
||||||
|
void setBorderColor(int borderColor);
|
||||||
|
void setBorderStrokeWidth(int borderStrokeWidth);
|
||||||
|
void setBorderLineLength(int borderLineLength);
|
||||||
|
void setLaserEnabled(boolean isLaserEnabled);
|
||||||
|
|
||||||
|
void setBorderCornerRounded(boolean isBorderCornersRounded);
|
||||||
|
void setBorderAlpha(float alpha);
|
||||||
|
void setBorderCornerRadius(int borderCornersRadius);
|
||||||
|
void setViewFinderOffset(int offset);
|
||||||
|
void setSquareViewFinder(boolean isSquareViewFinder);
|
||||||
|
/**
|
||||||
|
* Method that executes when Camera preview is starting.
|
||||||
|
* It is recommended to update framing rect here and invalidate view after that. <br/>
|
||||||
|
* For example see: {@link ViewFinderView#setupViewFinder()}
|
||||||
|
*/
|
||||||
|
void setupViewFinder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides {@link Rect} that identifies area where barcode scanner can detect visual codes
|
||||||
|
* <p>Note: This rect is a area representation in absolute pixel values. <br/>
|
||||||
|
* For example: <br/>
|
||||||
|
* If View's size is 1024x800 so framing rect might be 500x400</p>
|
||||||
|
*
|
||||||
|
* @return {@link Rect} that identifies barcode scanner area
|
||||||
|
*/
|
||||||
|
Rect getFramingRect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Width of a {@link android.view.View} that implements this interface
|
||||||
|
* <p>Note: this is already implemented in {@link android.view.View},
|
||||||
|
* so you don't need to override method and provide your implementation</p>
|
||||||
|
*
|
||||||
|
* @return width of a view
|
||||||
|
*/
|
||||||
|
int getWidth();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Height of a {@link android.view.View} that implements this interface
|
||||||
|
* <p>Note: this is already implemented in {@link android.view.View},
|
||||||
|
* so you don't need to override method and provide your implementation</p>
|
||||||
|
*
|
||||||
|
* @return height of a view
|
||||||
|
*/
|
||||||
|
int getHeight();
|
||||||
|
}
|
259
library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/ViewFinderView.java
vendored
Normal file
259
library/external/barcodescanner/core/src/main/java/me/dm7/barcodescanner/core/ViewFinderView.java
vendored
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
package me.dm7.barcodescanner.core;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.CornerPathEffect;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Path;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
public class ViewFinderView extends View implements IViewFinder {
|
||||||
|
private static final String TAG = "ViewFinderView";
|
||||||
|
|
||||||
|
private Rect mFramingRect;
|
||||||
|
|
||||||
|
private static final float PORTRAIT_WIDTH_RATIO = 6f/8;
|
||||||
|
private static final float PORTRAIT_WIDTH_HEIGHT_RATIO = 0.75f;
|
||||||
|
|
||||||
|
private static final float LANDSCAPE_HEIGHT_RATIO = 5f/8;
|
||||||
|
private static final float LANDSCAPE_WIDTH_HEIGHT_RATIO = 1.4f;
|
||||||
|
private static final int MIN_DIMENSION_DIFF = 50;
|
||||||
|
|
||||||
|
private static final float DEFAULT_SQUARE_DIMENSION_RATIO = 5f / 8;
|
||||||
|
|
||||||
|
private static final int[] SCANNER_ALPHA = {0, 64, 128, 192, 255, 192, 128, 64};
|
||||||
|
private int scannerAlpha;
|
||||||
|
private static final int POINT_SIZE = 10;
|
||||||
|
private static final long ANIMATION_DELAY = 80l;
|
||||||
|
|
||||||
|
private final int mDefaultLaserColor = getResources().getColor(R.color.viewfinder_laser);
|
||||||
|
private final int mDefaultMaskColor = getResources().getColor(R.color.viewfinder_mask);
|
||||||
|
private final int mDefaultBorderColor = getResources().getColor(R.color.viewfinder_border);
|
||||||
|
private final int mDefaultBorderStrokeWidth = getResources().getInteger(R.integer.viewfinder_border_width);
|
||||||
|
private final int mDefaultBorderLineLength = getResources().getInteger(R.integer.viewfinder_border_length);
|
||||||
|
|
||||||
|
protected Paint mLaserPaint;
|
||||||
|
protected Paint mFinderMaskPaint;
|
||||||
|
protected Paint mBorderPaint;
|
||||||
|
protected int mBorderLineLength;
|
||||||
|
protected boolean mSquareViewFinder;
|
||||||
|
private boolean mIsLaserEnabled;
|
||||||
|
private float mBordersAlpha;
|
||||||
|
private int mViewFinderOffset = 0;
|
||||||
|
|
||||||
|
public ViewFinderView(Context context) {
|
||||||
|
super(context);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ViewFinderView(Context context, AttributeSet attributeSet) {
|
||||||
|
super(context, attributeSet);
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init() {
|
||||||
|
//set up laser paint
|
||||||
|
mLaserPaint = new Paint();
|
||||||
|
mLaserPaint.setColor(mDefaultLaserColor);
|
||||||
|
mLaserPaint.setStyle(Paint.Style.FILL);
|
||||||
|
|
||||||
|
//finder mask paint
|
||||||
|
mFinderMaskPaint = new Paint();
|
||||||
|
mFinderMaskPaint.setColor(mDefaultMaskColor);
|
||||||
|
|
||||||
|
//border paint
|
||||||
|
mBorderPaint = new Paint();
|
||||||
|
mBorderPaint.setColor(mDefaultBorderColor);
|
||||||
|
mBorderPaint.setStyle(Paint.Style.STROKE);
|
||||||
|
mBorderPaint.setStrokeWidth(mDefaultBorderStrokeWidth);
|
||||||
|
mBorderPaint.setAntiAlias(true);
|
||||||
|
|
||||||
|
mBorderLineLength = mDefaultBorderLineLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLaserColor(int laserColor) {
|
||||||
|
mLaserPaint.setColor(laserColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMaskColor(int maskColor) {
|
||||||
|
mFinderMaskPaint.setColor(maskColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBorderColor(int borderColor) {
|
||||||
|
mBorderPaint.setColor(borderColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBorderStrokeWidth(int borderStrokeWidth) {
|
||||||
|
mBorderPaint.setStrokeWidth(borderStrokeWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBorderLineLength(int borderLineLength) {
|
||||||
|
mBorderLineLength = borderLineLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLaserEnabled(boolean isLaserEnabled) { mIsLaserEnabled = isLaserEnabled; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBorderCornerRounded(boolean isBorderCornersRounded) {
|
||||||
|
if (isBorderCornersRounded) {
|
||||||
|
mBorderPaint.setStrokeJoin(Paint.Join.ROUND);
|
||||||
|
} else {
|
||||||
|
mBorderPaint.setStrokeJoin(Paint.Join.BEVEL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBorderAlpha(float alpha) {
|
||||||
|
int colorAlpha = (int) (255 * alpha);
|
||||||
|
mBordersAlpha = alpha;
|
||||||
|
mBorderPaint.setAlpha(colorAlpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBorderCornerRadius(int borderCornersRadius) {
|
||||||
|
mBorderPaint.setPathEffect(new CornerPathEffect(borderCornersRadius));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setViewFinderOffset(int offset) {
|
||||||
|
mViewFinderOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Need a better way to configure this. Revisit when working on 2.0
|
||||||
|
@Override
|
||||||
|
public void setSquareViewFinder(boolean set) {
|
||||||
|
mSquareViewFinder = set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setupViewFinder() {
|
||||||
|
updateFramingRect();
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rect getFramingRect() {
|
||||||
|
return mFramingRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDraw(Canvas canvas) {
|
||||||
|
if(getFramingRect() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
drawViewFinderMask(canvas);
|
||||||
|
drawViewFinderBorder(canvas);
|
||||||
|
|
||||||
|
if (mIsLaserEnabled) {
|
||||||
|
drawLaser(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawViewFinderMask(Canvas canvas) {
|
||||||
|
int width = canvas.getWidth();
|
||||||
|
int height = canvas.getHeight();
|
||||||
|
Rect framingRect = getFramingRect();
|
||||||
|
|
||||||
|
canvas.drawRect(0, 0, width, framingRect.top, mFinderMaskPaint);
|
||||||
|
canvas.drawRect(0, framingRect.top, framingRect.left, framingRect.bottom + 1, mFinderMaskPaint);
|
||||||
|
canvas.drawRect(framingRect.right + 1, framingRect.top, width, framingRect.bottom + 1, mFinderMaskPaint);
|
||||||
|
canvas.drawRect(0, framingRect.bottom + 1, width, height, mFinderMaskPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawViewFinderBorder(Canvas canvas) {
|
||||||
|
Rect framingRect = getFramingRect();
|
||||||
|
|
||||||
|
// Top-left corner
|
||||||
|
Path path = new Path();
|
||||||
|
path.moveTo(framingRect.left, framingRect.top + mBorderLineLength);
|
||||||
|
path.lineTo(framingRect.left, framingRect.top);
|
||||||
|
path.lineTo(framingRect.left + mBorderLineLength, framingRect.top);
|
||||||
|
canvas.drawPath(path, mBorderPaint);
|
||||||
|
|
||||||
|
// Top-right corner
|
||||||
|
path.moveTo(framingRect.right, framingRect.top + mBorderLineLength);
|
||||||
|
path.lineTo(framingRect.right, framingRect.top);
|
||||||
|
path.lineTo(framingRect.right - mBorderLineLength, framingRect.top);
|
||||||
|
canvas.drawPath(path, mBorderPaint);
|
||||||
|
|
||||||
|
// Bottom-right corner
|
||||||
|
path.moveTo(framingRect.right, framingRect.bottom - mBorderLineLength);
|
||||||
|
path.lineTo(framingRect.right, framingRect.bottom);
|
||||||
|
path.lineTo(framingRect.right - mBorderLineLength, framingRect.bottom);
|
||||||
|
canvas.drawPath(path, mBorderPaint);
|
||||||
|
|
||||||
|
// Bottom-left corner
|
||||||
|
path.moveTo(framingRect.left, framingRect.bottom - mBorderLineLength);
|
||||||
|
path.lineTo(framingRect.left, framingRect.bottom);
|
||||||
|
path.lineTo(framingRect.left + mBorderLineLength, framingRect.bottom);
|
||||||
|
canvas.drawPath(path, mBorderPaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawLaser(Canvas canvas) {
|
||||||
|
Rect framingRect = getFramingRect();
|
||||||
|
|
||||||
|
// Draw a red "laser scanner" line through the middle to show decoding is active
|
||||||
|
mLaserPaint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
|
||||||
|
scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
|
||||||
|
int middle = framingRect.height() / 2 + framingRect.top;
|
||||||
|
canvas.drawRect(framingRect.left + 2, middle - 1, framingRect.right - 1, middle + 2, mLaserPaint);
|
||||||
|
|
||||||
|
postInvalidateDelayed(ANIMATION_DELAY,
|
||||||
|
framingRect.left - POINT_SIZE,
|
||||||
|
framingRect.top - POINT_SIZE,
|
||||||
|
framingRect.right + POINT_SIZE,
|
||||||
|
framingRect.bottom + POINT_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld) {
|
||||||
|
updateFramingRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void updateFramingRect() {
|
||||||
|
Point viewResolution = new Point(getWidth(), getHeight());
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int orientation = DisplayUtils.getScreenOrientation(getContext());
|
||||||
|
|
||||||
|
if(mSquareViewFinder) {
|
||||||
|
if(orientation != Configuration.ORIENTATION_PORTRAIT) {
|
||||||
|
height = (int) (getHeight() * DEFAULT_SQUARE_DIMENSION_RATIO);
|
||||||
|
width = height;
|
||||||
|
} else {
|
||||||
|
width = (int) (getWidth() * DEFAULT_SQUARE_DIMENSION_RATIO);
|
||||||
|
height = width;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(orientation != Configuration.ORIENTATION_PORTRAIT) {
|
||||||
|
height = (int) (getHeight() * LANDSCAPE_HEIGHT_RATIO);
|
||||||
|
width = (int) (LANDSCAPE_WIDTH_HEIGHT_RATIO * height);
|
||||||
|
} else {
|
||||||
|
width = (int) (getWidth() * PORTRAIT_WIDTH_RATIO);
|
||||||
|
height = (int) (PORTRAIT_WIDTH_HEIGHT_RATIO * width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(width > getWidth()) {
|
||||||
|
width = getWidth() - MIN_DIMENSION_DIFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(height > getHeight()) {
|
||||||
|
height = getHeight() - MIN_DIMENSION_DIFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
int leftOffset = (viewResolution.x - width) / 2;
|
||||||
|
int topOffset = (viewResolution.y - height) / 2;
|
||||||
|
mFramingRect = new Rect(leftOffset + mViewFinderOffset, topOffset + mViewFinderOffset, leftOffset + width - mViewFinderOffset, topOffset + height - mViewFinderOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<integer name="viewfinder_border_width">4</integer>
|
||||||
|
<integer name="viewfinder_border_length">60</integer>
|
||||||
|
</resources>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<integer name="viewfinder_border_width">5</integer>
|
||||||
|
<integer name="viewfinder_border_length">80</integer>
|
||||||
|
</resources>
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<integer name="viewfinder_border_width">6</integer>
|
||||||
|
<integer name="viewfinder_border_length">100</integer>
|
||||||
|
</resources>
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<declare-styleable name="BarcodeScannerView">
|
||||||
|
<attr name="shouldScaleToFill" format="boolean" />
|
||||||
|
<attr name="laserEnabled" format="boolean" />
|
||||||
|
<attr name="laserColor" format="color" />
|
||||||
|
<attr name="borderColor" format="color" />
|
||||||
|
<attr name="maskColor" format="color" />
|
||||||
|
<attr name="borderWidth" format="dimension" />
|
||||||
|
<attr name="borderLength" format="dimension" />
|
||||||
|
<attr name="roundedCorner" format="boolean" />
|
||||||
|
<attr name="cornerRadius" format="dimension" />
|
||||||
|
<attr name="squaredFinder" format="boolean" />
|
||||||
|
<attr name="borderAlpha" format="float" />
|
||||||
|
<attr name="finderOffset" format="dimension" />
|
||||||
|
</declare-styleable>
|
||||||
|
</resources>
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<color name="viewfinder_mask">#60000000</color>
|
||||||
|
<color name="viewfinder_laser">#ffcc0000</color>
|
||||||
|
<color name="viewfinder_border">#ffafed44</color>
|
||||||
|
</resources>
|
|
@ -0,0 +1,4 @@
|
||||||
|
<resources>
|
||||||
|
<integer name="viewfinder_border_width">4</integer>
|
||||||
|
<integer name="viewfinder_border_length">60</integer>
|
||||||
|
</resources>
|
|
@ -0,0 +1,29 @@
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace "me.dm7.barcodescanner.zxing"
|
||||||
|
|
||||||
|
compileSdk versions.compileSdk
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdk versions.minSdk
|
||||||
|
targetSdk versions.targetSdk
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility versions.sourceCompat
|
||||||
|
targetCompatibility versions.targetCompat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api project(":library:external:barcodescanner:core")
|
||||||
|
// Stick to 3.3.3 because of https://github.com/zxing/zxing/issues/1170
|
||||||
|
api 'com.google.zxing:core:3.3.3'
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
tasks.findAll { it.name.startsWith("lint") }.each {
|
||||||
|
it.enabled = false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,198 @@
|
||||||
|
package me.dm7.barcodescanner.zxing;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.hardware.Camera;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.zxing.BarcodeFormat;
|
||||||
|
import com.google.zxing.BinaryBitmap;
|
||||||
|
import com.google.zxing.DecodeHintType;
|
||||||
|
import com.google.zxing.LuminanceSource;
|
||||||
|
import com.google.zxing.MultiFormatReader;
|
||||||
|
import com.google.zxing.NotFoundException;
|
||||||
|
import com.google.zxing.PlanarYUVLuminanceSource;
|
||||||
|
import com.google.zxing.ReaderException;
|
||||||
|
import com.google.zxing.Result;
|
||||||
|
import com.google.zxing.common.HybridBinarizer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import me.dm7.barcodescanner.core.BarcodeScannerView;
|
||||||
|
import me.dm7.barcodescanner.core.DisplayUtils;
|
||||||
|
|
||||||
|
public class ZXingScannerView extends BarcodeScannerView {
|
||||||
|
private static final String TAG = "ZXingScannerView";
|
||||||
|
|
||||||
|
public interface ResultHandler {
|
||||||
|
void handleResult(Result rawResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MultiFormatReader mMultiFormatReader;
|
||||||
|
public static final List<BarcodeFormat> ALL_FORMATS = new ArrayList<>();
|
||||||
|
private List<BarcodeFormat> mFormats;
|
||||||
|
private ResultHandler mResultHandler;
|
||||||
|
|
||||||
|
static {
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.AZTEC);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.CODABAR);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.CODE_39);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.CODE_93);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.CODE_128);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.DATA_MATRIX);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.EAN_8);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.EAN_13);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.ITF);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.MAXICODE);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.PDF_417);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.QR_CODE);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.RSS_14);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.RSS_EXPANDED);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.UPC_A);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.UPC_E);
|
||||||
|
ALL_FORMATS.add(BarcodeFormat.UPC_EAN_EXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZXingScannerView(Context context) {
|
||||||
|
super(context);
|
||||||
|
initMultiFormatReader();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZXingScannerView(Context context, AttributeSet attributeSet) {
|
||||||
|
super(context, attributeSet);
|
||||||
|
initMultiFormatReader();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormats(List<BarcodeFormat> formats) {
|
||||||
|
mFormats = formats;
|
||||||
|
initMultiFormatReader();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResultHandler(ResultHandler resultHandler) {
|
||||||
|
mResultHandler = resultHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<BarcodeFormat> getFormats() {
|
||||||
|
if(mFormats == null) {
|
||||||
|
return ALL_FORMATS;
|
||||||
|
}
|
||||||
|
return mFormats;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initMultiFormatReader() {
|
||||||
|
Map<DecodeHintType,Object> hints = new EnumMap<>(DecodeHintType.class);
|
||||||
|
hints.put(DecodeHintType.POSSIBLE_FORMATS, getFormats());
|
||||||
|
mMultiFormatReader = new MultiFormatReader();
|
||||||
|
mMultiFormatReader.setHints(hints);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPreviewFrame(byte[] data, Camera camera) {
|
||||||
|
if(mResultHandler == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Camera.Parameters parameters = camera.getParameters();
|
||||||
|
Camera.Size size = parameters.getPreviewSize();
|
||||||
|
int width = size.width;
|
||||||
|
int height = size.height;
|
||||||
|
|
||||||
|
if (DisplayUtils.getScreenOrientation(getContext()) == Configuration.ORIENTATION_PORTRAIT) {
|
||||||
|
int rotationCount = getRotationCount();
|
||||||
|
if (rotationCount == 1 || rotationCount == 3) {
|
||||||
|
int tmp = width;
|
||||||
|
width = height;
|
||||||
|
height = tmp;
|
||||||
|
}
|
||||||
|
data = getRotatedData(data, camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result rawResult = null;
|
||||||
|
PlanarYUVLuminanceSource source = buildLuminanceSource(data, width, height);
|
||||||
|
|
||||||
|
if (source != null) {
|
||||||
|
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||||
|
try {
|
||||||
|
rawResult = mMultiFormatReader.decodeWithState(bitmap);
|
||||||
|
} catch (ReaderException re) {
|
||||||
|
// continue
|
||||||
|
} catch (NullPointerException npe) {
|
||||||
|
// This is terrible
|
||||||
|
} catch (ArrayIndexOutOfBoundsException aoe) {
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
mMultiFormatReader.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawResult == null) {
|
||||||
|
LuminanceSource invertedSource = source.invert();
|
||||||
|
bitmap = new BinaryBitmap(new HybridBinarizer(invertedSource));
|
||||||
|
try {
|
||||||
|
rawResult = mMultiFormatReader.decodeWithState(bitmap);
|
||||||
|
} catch (NotFoundException e) {
|
||||||
|
// continue
|
||||||
|
} finally {
|
||||||
|
mMultiFormatReader.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Result finalRawResult = rawResult;
|
||||||
|
|
||||||
|
if (finalRawResult != null) {
|
||||||
|
Handler handler = new Handler(Looper.getMainLooper());
|
||||||
|
handler.post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Stopping the preview can take a little long.
|
||||||
|
// So we want to set result handler to null to discard subsequent calls to
|
||||||
|
// onPreviewFrame.
|
||||||
|
ResultHandler tmpResultHandler = mResultHandler;
|
||||||
|
mResultHandler = null;
|
||||||
|
|
||||||
|
stopCameraPreview();
|
||||||
|
if (tmpResultHandler != null) {
|
||||||
|
tmpResultHandler.handleResult(finalRawResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
camera.setOneShotPreviewCallback(this);
|
||||||
|
}
|
||||||
|
} catch(RuntimeException e) {
|
||||||
|
// TODO: Terrible hack. It is possible that this method is invoked after camera is released.
|
||||||
|
Log.e(TAG, e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resumeCameraPreview(ResultHandler resultHandler) {
|
||||||
|
mResultHandler = resultHandler;
|
||||||
|
super.resumeCameraPreview();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
|
||||||
|
Rect rect = getFramingRectInPreview(width, height);
|
||||||
|
if (rect == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Go ahead and assume it's YUV rather than die.
|
||||||
|
PlanarYUVLuminanceSource source = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
source = new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
|
||||||
|
rect.width(), rect.height(), false);
|
||||||
|
} catch(Exception e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,8 @@ include ':library:external:textdrawable'
|
||||||
include ':library:external:autocomplete'
|
include ':library:external:autocomplete'
|
||||||
include ':library:external:realmfieldnameshelper'
|
include ':library:external:realmfieldnameshelper'
|
||||||
include ':library:external:span'
|
include ':library:external:span'
|
||||||
|
include ':library:external:barcodescanner:core'
|
||||||
|
include ':library:external:barcodescanner:zxing'
|
||||||
|
|
||||||
include ':library:rustCrypto'
|
include ':library:rustCrypto'
|
||||||
include ':matrix-sdk-android'
|
include ':matrix-sdk-android'
|
||||||
|
|
|
@ -263,11 +263,7 @@ dependencies {
|
||||||
// Stick to 3.3.3 because of https://github.com/zxing/zxing/issues/1170
|
// Stick to 3.3.3 because of https://github.com/zxing/zxing/issues/1170
|
||||||
implementation 'com.google.zxing:core:3.3.3'
|
implementation 'com.google.zxing:core:3.3.3'
|
||||||
|
|
||||||
// Excludes the legacy support library annotation usages
|
implementation project(":library:external:barcodescanner:zxing")
|
||||||
// https://github.com/dm77/barcodescanner/blob/d036996c8a6f36a68843ffe539c834c28944b2d5/core/src/main/java/me/dm7/barcodescanner/core/CameraWrapper.java#L4
|
|
||||||
implementation ('me.dm7.barcodescanner:zxing:1.9.13') {
|
|
||||||
exclude group: 'com.android.support', module: 'support-v4'
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emoji Keyboard
|
// Emoji Keyboard
|
||||||
api libs.vanniktech.emojiMaterial
|
api libs.vanniktech.emojiMaterial
|
||||||
|
|
Loading…
Reference in New Issue