This commit is contained in:
2025-11-18 15:25:59 +08:00
parent 790f719050
commit 69f2eaf336
1227 changed files with 89317 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
/build
+61
View File
@@ -0,0 +1,61 @@
apply plugin: 'com.android.library'
version = "1.4.2" // 修改为你的版本号
android {
namespace 'cn.bertsir.zbar'
compileSdkVersion 25
defaultConfig {
minSdkVersion 15
targetSdkVersion 22
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:25.3.1'
implementation 'com.google.zxing:core:3.3.0'
implementation 'com.soundcloud.android:android-crop:1.0.1@aar'
// 基础依赖包,必须要依赖
implementation 'com.gyf.immersionbar:immersionbar:3.0.0'
}
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
}
task androidJavadocsJar(type: Jar) {
archiveClassifier.set('javadoc')
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar) {
archiveClassifier.set('sources')
from android.sourceSets.main.java.srcDirs
}
artifacts {
archives androidSourcesJar
archives androidJavadocsJar
}
Properties properties = new Properties()
// 加载本地配置
properties.load(project.rootProject.file('local.properties').newDataInputStream())
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+25
View File
@@ -0,0 +1,25 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:\DevelopTools\android-sdk-windows-as/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
+44
View File
@@ -0,0 +1,44 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.bertsir.zbar"
>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-feature android:name="android.hardware.camera.autofocus"/>
<uses-permission android:name="android.permission.FLASHLIGHT"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true"
>
<provider
android:name=".utils.QrFileProvider"
android:authorities="${applicationId}.zbar.FileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/qr_file_paths"/>
</provider>
<activity android:name="cn.bertsir.zbar.QRActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
/>
<activity
android:name=".utils.PermissionUtils$PermissionActivity"
android:theme="@style/ActivityTranslucent"
/>
<activity android:name="com.soundcloud.android.crop.CropImageActivity" />
</application>
</manifest>
@@ -0,0 +1,211 @@
/*
* Copyright © Yan Zhenjie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.bertsir.zbar;
import android.content.Context;
import android.graphics.Point;
import android.hardware.Camera;
import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.WindowManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
/**
* <p>Camera config.</p>
*/
public final class CameraConfiguration {
private static final String TAG = "CameraConfiguration";
private static final int MIN_PREVIEW_PIXELS = 480 * 320;
private static final double MAX_ASPECT_DISTORTION = 0.15;
private final Context context;
private Point screenResolution;
private Point cameraResolution;
public CameraConfiguration(Context context) {
this.context = context;
}
@SuppressWarnings("SuspiciousNameCombination")
public void initFromCameraParameters(Camera camera) {
Camera.Parameters parameters = camera.getParameters();
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = manager.getDefaultDisplay();
screenResolution = getDisplaySize(display);
Point screenResolutionForCamera = new Point();
screenResolutionForCamera.x = screenResolution.x;
screenResolutionForCamera.y = screenResolution.y;
// Convert to vertical screen.
if (screenResolution.x < screenResolution.y) {
screenResolutionForCamera.x = screenResolution.y;
screenResolutionForCamera.y = screenResolution.x;
}
cameraResolution = findBestPreviewSizeValue(parameters, screenResolutionForCamera);
}
private Point getDisplaySize(final Display display) {
final Point point = new Point();
if (Build.VERSION.SDK_INT >= 13)
display.getSize(point);
else {
point.set(display.getWidth(), display.getHeight());
}
return point;
}
public void setDesiredCameraParameters(Camera camera, boolean safeMode) {
Camera.Parameters parameters = camera.getParameters();
if (parameters == null) {
Log.w(TAG, "Device error: no camera parameters are available. Proceeding without configuration.");
return;
}
parameters.setPreviewSize(cameraResolution.x, cameraResolution.y);
camera.setParameters(parameters);
Camera.Parameters afterParameters = camera.getParameters();
Camera.Size afterSize = afterParameters.getPreviewSize();
if (afterSize != null && (cameraResolution.x != afterSize.width || cameraResolution.y != afterSize.height)) {
cameraResolution.x = afterSize.width;
cameraResolution.y = afterSize.height;
}
camera.setDisplayOrientation(90);
}
/**
* Camera resolution.
*
* @return {@link Point}.
*/
public Point getCameraResolution() {
return cameraResolution;
}
/**
* Screen resolution.
*
* @return {@link Point}.
*/
public Point getScreenResolution() {
return screenResolution;
}
/**
* Calculate the preview interface size.
*
* @param parameters camera params.
* @param screenResolution screen resolution.
* @return {@link Point}.
*/
private Point findBestPreviewSizeValue(Camera.Parameters parameters, Point screenResolution) {
List<Camera.Size> rawSupportedSizes = parameters.getSupportedPreviewSizes();
if (rawSupportedSizes == null) {
Log.w(TAG, "Device returned no supported preview sizes; using default");
Camera.Size defaultSize = parameters.getPreviewSize();
return new Point(defaultSize.width, defaultSize.height);
}
// Sort by size, descending
List<Camera.Size> supportedPreviewSizes = new ArrayList<>(rawSupportedSizes);
Collections.sort(supportedPreviewSizes, new Comparator<Camera.Size>() {
@Override
public int compare(Camera.Size a, Camera.Size b) {
int aPixels = a.height * a.width;
int bPixels = b.height * b.width;
if (bPixels < aPixels) {
return -1;
}
if (bPixels > aPixels) {
return 1;
}
return 0;
}
});
if (Log.isLoggable(TAG, Log.INFO)) {
StringBuilder previewSizesString = new StringBuilder();
for (Camera.Size supportedPreviewSize : supportedPreviewSizes) {
previewSizesString.append(supportedPreviewSize.width)
.append('x')
.append(supportedPreviewSize.height)
.append(' ');
}
Log.i(TAG, "Supported preview sizes: " + previewSizesString);
}
double screenAspectRatio = (double) screenResolution.x / (double) screenResolution.y;
// Remove sizes that are unsuitable
Iterator<Camera.Size> it = supportedPreviewSizes.iterator();
while (it.hasNext()) {
Camera.Size supportedPreviewSize = it.next();
int realWidth = supportedPreviewSize.width;
int realHeight = supportedPreviewSize.height;
if (realWidth * realHeight < MIN_PREVIEW_PIXELS) {
it.remove();
continue;
}
boolean isCandidatePortrait = realWidth < realHeight;
int maybeFlippedWidth = isCandidatePortrait ? realHeight : realWidth;
int maybeFlippedHeight = isCandidatePortrait ? realWidth : realHeight;
double aspectRatio = (double) maybeFlippedWidth / (double) maybeFlippedHeight;
double distortion = Math.abs(aspectRatio - screenAspectRatio);
if (distortion > MAX_ASPECT_DISTORTION) {
it.remove();
continue;
}
if (maybeFlippedWidth == screenResolution.x && maybeFlippedHeight == screenResolution.y) {
Point exactPoint = new Point(realWidth, realHeight);
Log.i(TAG, "Found preview size exactly matching screen size: " + exactPoint);
return exactPoint;
}
}
// If no exact match, use largest preview size. This was not a great
// idea on older devices because
// of the additional computation needed. We're likely to get here on
// newer Android 4+ devices, where
// the CPU is much more powerful.
if (!supportedPreviewSizes.isEmpty()) {
Camera.Size largestPreview = supportedPreviewSizes.get(0);
Point largestSize = new Point(largestPreview.width, largestPreview.height);
Log.i(TAG, "Using largest suitable preview size: " + largestSize);
return largestSize;
}
// If there is nothing at all suitable, return current preview size
Camera.Size defaultPreview = parameters.getPreviewSize();
Point defaultSize = new Point(defaultPreview.width, defaultPreview.height);
Log.i(TAG, "No suitable preview sizes, using default: " + defaultSize);
return defaultSize;
}
}
@@ -0,0 +1,238 @@
/*
* Copyright © Yan Zhenjie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.bertsir.zbar;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import java.io.IOException;
import cn.bertsir.zbar.utils.QRUtils;
/**
* <p>Camera manager.</p>
*/
public final class CameraManager {
private static final String TAG = "CameraManager";
private final CameraConfiguration mConfiguration;
private Context context;
private Camera mCamera;
public CameraManager(Context context) {
this.context = context;
this.mConfiguration = new CameraConfiguration(context);
}
/**
* Opens the mCamera driver and initializes the hardware parameters.
*
* @throws Exception ICamera open failed, occupied or abnormal.
*/
public synchronized void openDriver() throws Exception {
if (mCamera != null) return;
mCamera = Camera.open();
if (mCamera == null) throw new IOException("The camera is occupied.");
mConfiguration.initFromCameraParameters(mCamera);
Camera.Parameters parameters = mCamera.getParameters();
String parametersFlattened = parameters == null ? null : parameters.flatten();
try {
mConfiguration.setDesiredCameraParameters(mCamera, false);
} catch (RuntimeException re) {
if (parametersFlattened != null) {
parameters = mCamera.getParameters();
parameters.unflatten(parametersFlattened);
try {
mCamera.setParameters(parameters);
mConfiguration.setDesiredCameraParameters(mCamera, true);
} catch (RuntimeException e) {
e.printStackTrace();
}
}
}
}
/**
* Closes the camera driver if still in use.
*/
public synchronized void closeDriver() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
}
}
/**
* Camera is opened.
*
* @return true, other wise false.
*/
public boolean isOpen() {
return mCamera != null;
}
/**
* Get camera configuration.
*
* @return {@link CameraConfiguration}.
*/
public CameraConfiguration getConfiguration() {
return mConfiguration;
}
/**
* Camera start preview.
*
* @param holder {@link SurfaceHolder}.
* @param previewCallback {@link Camera.PreviewCallback}.
* @throws IOException if the method fails (for example, if the surface is unavailable or unsuitable).
*/
public void startPreview(SurfaceHolder holder, Camera.PreviewCallback previewCallback) throws IOException {
if (mCamera != null) {
//解决nexus5x扫码倒立的情况
if(android.os.Build.MANUFACTURER.equals("LGE") &&
android.os.Build.MODEL.equals("Nexus 5X")) {
mCamera.setDisplayOrientation(QRUtils.getInstance().isScreenOriatationPortrait(context) ? 270 : 180);
}else {
mCamera.setDisplayOrientation(QRUtils.getInstance().isScreenOriatationPortrait(context) ? 90 : 0);
}
mCamera.setPreviewDisplay(holder);
mCamera.setPreviewCallback(previewCallback);
mCamera.startPreview();
}
}
/**
* Camera stop preview.
*/
public void stopPreview() {
if (mCamera != null) {
try {
mCamera.stopPreview();
} catch (Exception ignored) {
// nothing.
}
try {
mCamera.setPreviewDisplay(null);
} catch (IOException ignored) {
// nothing.
}
}
}
/**
* Focus on, make a scan action.
*
* @param callback {@link Camera.AutoFocusCallback}.
*/
public void autoFocus(Camera.AutoFocusCallback callback) {
if (mCamera != null)
try {
mCamera.autoFocus(callback);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* set Camera Flash
*/
public void setFlash(){
if(mCamera != null){
Camera.Parameters parameters = mCamera.getParameters();
if(parameters.getFlashMode() == null) {
return;
}
if(parameters.getFlashMode().endsWith(Camera.Parameters.FLASH_MODE_TORCH)){
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}else {
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
}
mCamera.setParameters(parameters);
}
}
/**
* set Camera Flash
*/
public void setFlash(boolean open){
if(mCamera != null){
Camera.Parameters parameters = mCamera.getParameters();
if(parameters.getFlashMode() == null) {
return;
}
if(!open){
if(parameters.getFlashMode().endsWith(Camera.Parameters.FLASH_MODE_TORCH)){
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
}
}else {
if(parameters.getFlashMode().endsWith(Camera.Parameters.FLASH_MODE_OFF)){
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
}
}
mCamera.setParameters(parameters);
}
}
/**
* 相机设置焦距
*/
public void setCameraZoom(float ratio){
if(mCamera != null){
Camera.Parameters parameters = mCamera.getParameters();
if(!parameters.isZoomSupported()){
return;
}
int maxZoom = parameters.getMaxZoom();
if(maxZoom == 0){
return;
}
int zoom = (int) (maxZoom * ratio);
parameters.setZoom(zoom);
mCamera.setParameters(parameters);
}
}
public void handleZoom(boolean isZoomIn) {
if(mCamera != null){
Camera.Parameters params = mCamera.getParameters();
if (params.isZoomSupported()) {
int maxZoom = params.getMaxZoom();
int zoom = params.getZoom();
if (isZoomIn && zoom < maxZoom) {
zoom++;
} else if (zoom > 0) {
zoom--;
}
params.setZoom(zoom);
mCamera.setParameters(params);
} else {
Log.i(TAG, "zoom not supported");
}
}
}
}
@@ -0,0 +1,168 @@
/*
* Copyright © Yan Zhenjie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.bertsir.zbar;
import android.content.Context;
import android.hardware.Camera;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Toast;
/**
* <p>QRCode Camera preview, include QRCode recognition.</p>
*/
public class CameraPreview extends FrameLayout implements SurfaceHolder.Callback {
private CameraManager mCameraManager;
private CameraScanAnalysis mPreviewCallback;
private SurfaceView mSurfaceView;
private boolean isPreviewStart = false;
public CameraPreview(Context context) {
this(context, null);
}
public CameraPreview(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CameraPreview(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mCameraManager = new CameraManager(context);
mPreviewCallback = new CameraScanAnalysis(context);
}
/**
* Set Scan results callback.
*
* @param callback {@link ScanCallback}.
*/
public void setScanCallback(ScanCallback callback) {
mPreviewCallback.setScanCallback(callback);
}
/**
* Camera start preview.
*/
public boolean start() {
try {
mCameraManager.openDriver();
} catch (Exception e) {
Toast.makeText(getContext(), "摄像头权限被拒绝!", Toast.LENGTH_SHORT).show();
return false;
}
mPreviewCallback.onStart();
if (mSurfaceView == null) {
mSurfaceView = new SurfaceView(getContext());
addView(mSurfaceView, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
SurfaceHolder holder = mSurfaceView.getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
startCameraPreview(mSurfaceView.getHolder());
return true;
}
/**
* Camera stop preview.
*/
public void stop() {
removeCallbacks(mAutoFocusTask);
mPreviewCallback.onStop();
mCameraManager.stopPreview();
mCameraManager.closeDriver();
}
private void startCameraPreview(SurfaceHolder holder) {
try {
mCameraManager.startPreview(holder, mPreviewCallback);
mCameraManager.autoFocus(mFocusCallback);
isPreviewStart = true;
} catch (Exception e) {
e.printStackTrace();
//如果异常延迟200ms再试
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
mCameraManager.autoFocus(mFocusCallback);
}
}, 200);
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (holder.getSurface() == null) {
return;
}
mCameraManager.stopPreview();
startCameraPreview(holder);
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
private Camera.AutoFocusCallback mFocusCallback = new Camera.AutoFocusCallback() {
public void onAutoFocus(boolean success, Camera camera) {
postDelayed(mAutoFocusTask, 500);
}
};
private Runnable mAutoFocusTask = new Runnable() {
public void run() {
mCameraManager.autoFocus(mFocusCallback);
}
};
@Override
protected void onDetachedFromWindow() {
stop();
super.onDetachedFromWindow();
}
public void setFlash() {
mCameraManager.setFlash();
}
public void setFlash(boolean open) {
mCameraManager.setFlash(open);
}
public void setZoom(float zoom){
mCameraManager.setCameraZoom(zoom);
}
public void handleZoom(boolean isZoomIn){
mCameraManager.handleZoom(isZoomIn);
}
public boolean isPreviewStart(){
return this.isPreviewStart;
}
}
@@ -0,0 +1,316 @@
/*
* Copyright © Yan Zhenjie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.bertsir.zbar;
import android.content.Context;
import android.hardware.Camera;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
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.Reader;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.ResultPoint;
import com.google.zxing.common.DetectorResult;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.datamatrix.detector.Detector;
import com.google.zxing.qrcode.QRCodeReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import cn.bertsir.zbar.Qr.Config;
import cn.bertsir.zbar.Qr.Image;
import cn.bertsir.zbar.Qr.ImageScanner;
import cn.bertsir.zbar.Qr.ScanResult;
import cn.bertsir.zbar.Qr.Symbol;
import cn.bertsir.zbar.Qr.SymbolSet;
import cn.bertsir.zbar.utils.QRUtils;
/**
*/
class CameraScanAnalysis implements Camera.PreviewCallback {
private ExecutorService executorService = Executors.newSingleThreadExecutor();
private ImageScanner mImageScanner;
private Handler mHandler;
private ScanCallback mCallback;
private static final String TAG = "CameraScanAnalysis";
private boolean allowAnalysis = true;
private Image barcode;
private int cropWidth;
private int cropHeight;
private Camera.Size size;
private byte[] data;
private Camera camera;
private Context context;
private long lastResultTime = 0;
private MultiFormatReader multiFormatReader = new MultiFormatReader();
CameraScanAnalysis(Context context) {
this.context = context;
mImageScanner = new ImageScanner();
if (Symbol.scanType == QrConfig.TYPE_QRCODE) {
mImageScanner.setConfig(Symbol.NONE, Config.ENABLE, 0);
mImageScanner.setConfig(Symbol.QRCODE, Config.ENABLE, 1);
} else if (Symbol.scanType == QrConfig.TYPE_BARCODE) {
mImageScanner.setConfig(Symbol.NONE, Config.ENABLE, 0);
mImageScanner.setConfig(Symbol.CODE128, Config.ENABLE, 1);
mImageScanner.setConfig(Symbol.CODE39, Config.ENABLE, 1);
mImageScanner.setConfig(Symbol.EAN13, Config.ENABLE, 1);
mImageScanner.setConfig(Symbol.EAN8, Config.ENABLE, 1);
mImageScanner.setConfig(Symbol.UPCA, Config.ENABLE, 1);
mImageScanner.setConfig(Symbol.UPCE, Config.ENABLE, 1);
mImageScanner.setConfig(Symbol.UPCE, Config.ENABLE, 1);
} else if (Symbol.scanType == QrConfig.TYPE_ALL) {
mImageScanner.setConfig(Symbol.NONE, Config.X_DENSITY, 3);
mImageScanner.setConfig(Symbol.NONE, Config.Y_DENSITY, 3);
} else if (Symbol.scanType == QrConfig.TYPE_CUSTOM) {
mImageScanner.setConfig(Symbol.NONE, Config.ENABLE, 0);
mImageScanner.setConfig(Symbol.scanFormat, Config.ENABLE, 1);
} else {
mImageScanner.setConfig(Symbol.NONE, Config.X_DENSITY, 3);
mImageScanner.setConfig(Symbol.NONE, Config.Y_DENSITY, 3);
}
mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
if (mCallback != null) mCallback.onScanResult((ScanResult) msg.obj);
}
};
}
void setScanCallback(ScanCallback callback) {
this.mCallback = callback;
}
void onStop() {
this.allowAnalysis = false;
}
void onStart() {
this.allowAnalysis = true;
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
if (allowAnalysis) {
allowAnalysis = false;
this.data = data;
this.camera = camera;
size = camera.getParameters().getPreviewSize();
barcode = new Image(size.width, size.height, "Y800");
barcode.setData(data);
if (Symbol.is_only_scan_center) {
//用于框中的自动拉伸和对识别数据的裁剪
cropWidth = (int) (Symbol.cropWidth * (size.height / (float) Symbol.screenWidth));
cropHeight = (int) (Symbol.cropHeight * (size.width / (float) Symbol.screenHeight));
Symbol.cropX = size.width / 2 - cropHeight / 2;
Symbol.cropY = size.height / 2 - cropWidth / 2;
barcode.setCrop(Symbol.cropX, Symbol.cropY, cropHeight, cropWidth);
}else {
//用于全屏幕的自动拉升
Symbol.cropX =0;
Symbol.cropY = 0;
cropWidth = size.width;
cropHeight = size.height;
}
if(Symbol.looperScan && (System.currentTimeMillis() - lastResultTime < Symbol.looperWaitTime)){
allowAnalysis = true;
return;
}
executorService.execute(mAnalysisTask);
}
}
/**
* 相机设置焦距
*/
public void cameraZoom(Camera mCamera) {
if (mCamera != null) {
Camera.Parameters parameters = mCamera.getParameters();
if (!parameters.isZoomSupported()) {
return;
}
int maxZoom = parameters.getMaxZoom();
if (maxZoom == 0) {
return;
}
if (parameters.getZoom() + 10 > parameters.getMaxZoom()) {
return;
}
parameters.setZoom(parameters.getZoom() + 10);
mCamera.setParameters(parameters);
}
}
private Runnable mAnalysisTask = new Runnable() {
@Override
public void run() {
if (Symbol.is_auto_zoom && Symbol.scanType == QrConfig.TYPE_QRCODE
&& QRUtils.getInstance().isScreenOriatationPortrait(context)) {
if(Symbol.is_only_scan_center){
if (Symbol.cropX == 0 || Symbol.cropY == 0 || cropWidth == 0 || cropHeight == 0) {
return;
}
}
LuminanceSource source = new PlanarYUVLuminanceSource(data, size.width,
size.height, Symbol.cropX, Symbol.cropY, cropWidth, cropHeight, true);
if (source != null) {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
DetectorResult detectorResult = null;
try {
detectorResult = new Detector(bitmap.getBlackMatrix()).detect();
ResultPoint[] p = detectorResult.getPoints();
//计算扫描框中的二维码的宽度,两点间距离公式
float point1X = p[0].getX();
float point1Y = p[0].getY();
float point2X = p[1].getX();
float point2Y = p[1].getY();
int len = (int) Math.sqrt(Math.abs(point1X - point2X) * Math.abs(point1X - point2X) + Math.abs(point1Y - point2Y) * Math.abs(point1Y - point2Y));
int minZoomLen = 10;
if (len < cropWidth / 4 && len > minZoomLen) {
cameraZoom(camera);
}
} catch (NotFoundException e) {
e.printStackTrace();
}
}
}
int result = mImageScanner.scanImage(barcode);
String resultStr = null;
int resultType = -1;
if (result != 0) {
SymbolSet symSet = mImageScanner.getResults();
for (Symbol sym : symSet){
resultStr = sym.getData();
resultType= sym.getType();
}
}
if (!TextUtils.isEmpty(resultStr)) {
ScanResult scanResult = new ScanResult();
scanResult.setContent(resultStr);
scanResult.setType(resultType == Symbol.QRCODE ? ScanResult.CODE_QR : ScanResult.CODE_BAR);
Message message = mHandler.obtainMessage();
message.obj = scanResult;
message.sendToTarget();
lastResultTime = System.currentTimeMillis();
if (Symbol.looperScan) {
allowAnalysis = true;
}
} else {
if (Symbol.doubleEngine) {
decode(data, size.width, size.height);
} else {
allowAnalysis = true;
}
}
}
};
/**
* zxing解码
*
* @param data
* @param width
* @param height
*/
private void decode(byte[] data, int width, int height) {
Result rawResult = null;
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];
}
}
int tmp = width; // Here we are swapping, that's the difference to #11
width = height;
height = tmp;
data = rotatedData;
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data, width, height, 0,
0, width, height, true);
;
Hashtable<DecodeHintType, Object> scanOption = new Hashtable<>();
scanOption.put(DecodeHintType.CHARACTER_SET, "utf-8");
Collection<Reader> readers = new ArrayList<>();
readers.add((new QRCodeReader()));
scanOption.put(DecodeHintType.POSSIBLE_FORMATS,readers);
multiFormatReader.setHints(scanOption);
if (source != null) {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
rawResult = multiFormatReader.decodeWithState(bitmap);
String resultStr = rawResult.toString();
BarcodeFormat resultFormat = rawResult.getBarcodeFormat();
if (!TextUtils.isEmpty(resultStr)) {
ScanResult scanResult = new ScanResult();
scanResult.setContent(resultStr);
scanResult.setType(resultFormat == BarcodeFormat.QR_CODE ? ScanResult.CODE_QR : ScanResult.CODE_BAR);
Message message = mHandler.obtainMessage();
message.obj = scanResult;
message.sendToTarget();
lastResultTime = System.currentTimeMillis();
if (Symbol.looperScan) {
allowAnalysis = true;
}
} else allowAnalysis = true;
} catch (ReaderException re) {
allowAnalysis = true;
//Log.i("解码异常",re.toString());
} finally {
multiFormatReader.reset();
}
} else {
allowAnalysis = true;
}
}
}
@@ -0,0 +1,496 @@
package cn.bertsir.zbar;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.PorterDuff;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.SoundPool;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import com.gyf.immersionbar.ImmersionBar;
import com.soundcloud.android.crop.Crop;
import java.io.File;
import cn.bertsir.zbar.Qr.ScanResult;
import cn.bertsir.zbar.Qr.Symbol;
import cn.bertsir.zbar.utils.GetPathFromUri;
import cn.bertsir.zbar.utils.QRUtils;
import cn.bertsir.zbar.view.ScanView;
import cn.bertsir.zbar.view.VerticalSeekBar;
public class QRActivity extends Activity implements View.OnClickListener, SensorEventListener {
private CameraPreview cp;
private SoundPool soundPool;
private ScanView sv;
private ImageView mo_scanner_back;
private ImageView iv_flash;
private ImageView iv_album;
private static final String TAG = "QRActivity";
private TextView textDialog;
private TextView tv_title;
private FrameLayout fl_title;
private TextView tv_des;
private QrConfig options;
static final int REQUEST_IMAGE_GET = 1;
static final int REQUEST_PHOTO_CUT = 2;
public static final int RESULT_CANCELED = 401;
public final float AUTOLIGHTMIN = 10F;
private Uri uricropFile;
private String cropTempPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "cropQr.jpg";
private VerticalSeekBar vsb_zoom;
private AlertDialog progressDialog;
private float oldDist = 1f;
//用于检测光线
private SensorManager sensorManager;
private Sensor sensor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
// Log.i("zBarLibary", "version: "+BuildConfig.VERSION_NAME);
options = (QrConfig) getIntent().getExtras().get(QrConfig.EXTRA_THIS_CONFIG);
initParm();
setContentView(R.layout.activity_qr);
initView();
}
/**
* 初始化参数
*/
private void initParm() {
switch (options.getSCREEN_ORIENTATION()) {
case QrConfig.SCREEN_LANDSCAPE:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
break;
case QrConfig.SCREEN_PORTRAIT:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
case QrConfig.SCREEN_SENSOR:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
break;
default:
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
break;
}
Symbol.scanType = options.getScan_type();
Symbol.scanFormat = options.getCustombarcodeformat();
Symbol.is_only_scan_center = options.isOnly_center();
Symbol.is_auto_zoom = options.isAuto_zoom();
Symbol.doubleEngine = options.isDouble_engine();
Symbol.looperScan = options.isLoop_scan();
Symbol.looperWaitTime = options.getLoop_wait_time();
Symbol.screenWidth = QRUtils.getInstance().getScreenWidth(this);
Symbol.screenHeight = QRUtils.getInstance().getScreenHeight(this);
if (options.isAuto_light()) {
getSensorManager();
}
}
/**
* 初始化布局
*/
private void initView() {
cp = (CameraPreview) findViewById(R.id.cp);
//bi~
soundPool = new SoundPool(10, AudioManager.STREAM_SYSTEM, 5);
soundPool.load(this, options.getDing_path(), 1);
sv = (ScanView) findViewById(R.id.sv);
sv.setType(options.getScan_view_type());
mo_scanner_back = (ImageView) findViewById(R.id.mo_scanner_back);
mo_scanner_back.setOnClickListener(this);
mo_scanner_back.setImageResource(options.getBackImgRes());
iv_flash = (ImageView) findViewById(R.id.iv_flash);
iv_flash.setOnClickListener(this);
iv_flash.setImageResource(options.getLightImageRes());
iv_album = (ImageView) findViewById(R.id.iv_album);
iv_album.setOnClickListener(this);
iv_album.setImageResource(options.getAblumImageRes());
tv_title = (TextView) findViewById(R.id.tv_title);
fl_title = (FrameLayout) findViewById(R.id.fl_title);
ImmersionBar.with(this).keyboardEnable(true).statusBarDarkFont(true).titleBar(fl_title).init();
tv_des = (TextView) findViewById(R.id.tv_des);
vsb_zoom = (VerticalSeekBar) findViewById(R.id.vsb_zoom);
iv_album.setVisibility(options.isShow_light() ? View.VISIBLE : View.GONE);
fl_title.setVisibility(options.isShow_title() ? View.VISIBLE : View.GONE);
iv_flash.setVisibility(options.isShow_light() ? View.VISIBLE : View.GONE);
iv_album.setVisibility(options.isShow_album() ? View.VISIBLE : View.GONE);
tv_des.setVisibility(options.isShow_des() ? View.VISIBLE : View.GONE);
vsb_zoom.setVisibility(options.isShow_zoom() ? View.VISIBLE : View.GONE);
tv_des.setText(options.getDes_text());
tv_title.setText(options.getTitle_text());
fl_title.setBackgroundColor(options.getTITLE_BACKGROUND_COLOR());
tv_title.setTextColor(options.getTITLE_TEXT_COLOR());
sv.setCornerColor(options.getCORNER_COLOR());
sv.setLineSpeed(options.getLine_speed());
sv.setLineColor(options.getLINE_COLOR());
sv.setScanLineStyle(options.getLine_style());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
setSeekBarColor(vsb_zoom, options.getCORNER_COLOR());
}
vsb_zoom.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
cp.setZoom((progress / 100f));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
/**
* 获取光线传感器
*/
public void getSensorManager() {
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager != null) {
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
}
}
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
public void setSeekBarColor(SeekBar seekBar, int color) {
seekBar.getThumb().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
seekBar.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
}
/**
* 识别结果回调
*/
private ScanCallback resultCallback = new ScanCallback() {
@Override
public void onScanResult(ScanResult result) {
if (options.isPlay_sound()) {
soundPool.play(1, 1, 1, 0, 0, 1);
}
if (options.isShow_vibrator()) {
QRUtils.getInstance().getVibrator(getApplicationContext());
}
if (cp != null) {
cp.setFlash(false);
}
QrManager.getInstance().getResultCallback().onScanSuccess(result);
if (!Symbol.looperScan) {
finish();
}
}
};
@Override
public void onClick(View v) {
if (v.getId() == R.id.iv_album) {
fromAlbum();
} else if (v.getId() == R.id.iv_flash) {
if (cp != null) {
cp.setFlash();
}
} else if (v.getId() == R.id.mo_scanner_back) {
setResult(RESULT_CANCELED);//兼容混合开发
finish();
}
}
@Override
protected void onResume() {
super.onResume();
if (cp != null) {
cp.setScanCallback(resultCallback);
cp.start();
}
if (sensorManager != null) {
//一般在Resume方法中注册
/**
* 第三个参数决定传感器信息更新速度
* SensorManager.SENSOR_DELAY_NORMAL:一般
* SENSOR_DELAY_FASTEST:最快
* SENSOR_DELAY_GAME:比较快,适合游戏
* SENSOR_DELAY_UI:慢
*/
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
@Override
protected void onPause() {
super.onPause();
if (cp != null) {
cp.stop();
}
if (sensorManager != null) {
//解除注册
sensorManager.unregisterListener(this, sensor);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (cp != null) {
cp.setFlash(false);
cp.stop();
}
soundPool.release();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch (requestCode) {
case REQUEST_IMAGE_GET:
if (options.isNeed_crop()) {
cropPhoto(data.getData());
} else {
recognitionLocation(data.getData());
}
break;
case Crop.REQUEST_CROP:
recognitionLocation(uricropFile);
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
/**
* 从相册选择
*/
private void fromAlbum() {
if (QRUtils.getInstance().isMIUI()) {//是否是小米设备,是的话用到弹窗选取入口的方法去选取
Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
startActivityForResult(Intent.createChooser(intent, options.getOpen_album_text()), REQUEST_IMAGE_GET);
} else {//直接跳到系统相册去选取
Intent intent = new Intent();
if (Build.VERSION.SDK_INT < 19) {
intent.setAction(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
} else {
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
}
startActivityForResult(Intent.createChooser(intent, options.getOpen_album_text()), REQUEST_IMAGE_GET);
}
}
/**
* 识别本地
*
* @param uri
*/
private void recognitionLocation(Uri uri) {
final String imagePath = GetPathFromUri.getPath(this, uri);
textDialog = showProgressDialog();
textDialog.setText("请稍后...");
new Thread(new Runnable() {
@Override
public void run() {
try {
if (TextUtils.isEmpty(imagePath)) {
Toast.makeText(getApplicationContext(), "获取图片失败!", Toast.LENGTH_SHORT).show();
return;
}
//优先使用zbar识别一次二维码
final String qrcontent = QRUtils.getInstance().decodeQRcode(imagePath);
runOnUiThread(new Runnable() {
@Override
public void run() {
ScanResult scanResult = new ScanResult();
if (!TextUtils.isEmpty(qrcontent)) {
closeProgressDialog();
scanResult.setContent(qrcontent);
scanResult.setType(ScanResult.CODE_QR);
QrManager.getInstance().getResultCallback().onScanSuccess(scanResult);
QRUtils.getInstance().deleteTempFile(cropTempPath);//删除裁切的临时文件
finish();
} else {
//尝试用zxing再试一次识别二维码
final String qrcontent = QRUtils.getInstance().decodeQRcodeByZxing(imagePath);
if (!TextUtils.isEmpty(qrcontent)) {
closeProgressDialog();
scanResult.setContent(qrcontent);
scanResult.setType(ScanResult.CODE_QR);
QrManager.getInstance().getResultCallback().onScanSuccess(scanResult);
QRUtils.getInstance().deleteTempFile(cropTempPath);//删除裁切的临时文件
finish();
} else {
//再试试是不是条形码
try {
String barcontent = QRUtils.getInstance().decodeBarcode(imagePath);
if (!TextUtils.isEmpty(barcontent)) {
closeProgressDialog();
scanResult.setContent(barcontent);
scanResult.setType(ScanResult.CODE_BAR);
QrManager.getInstance().getResultCallback().onScanSuccess(scanResult);
QRUtils.getInstance().deleteTempFile(cropTempPath);//删除裁切的临时文件
finish();
} else {
Toast.makeText(getApplicationContext(), "识别失败!", Toast.LENGTH_SHORT).show();
closeProgressDialog();
}
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "识别异常!", Toast.LENGTH_SHORT).show();
closeProgressDialog();
e.printStackTrace();
}
}
}
}
});
} catch (Exception e) {
Toast.makeText(getApplicationContext(), "识别异常!", Toast.LENGTH_SHORT).show();
closeProgressDialog();
}
}
}).start();
}
/**
* 裁切照片
*
* @param uri
*/
public void cropPhoto(Uri uri) {
uricropFile = Uri.parse("file://" + "/" + cropTempPath);
Crop.of(uri, uricropFile).asSquare().start(this);
}
public TextView showProgressDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this, R.style.AlertDialogStyle);
builder.setCancelable(false);
View view = View.inflate(this, R.layout.dialog_loading, null);
builder.setView(view);
ProgressBar pb_loading = (ProgressBar) view.findViewById(R.id.pb_loading);
TextView tv_hint = (TextView) view.findViewById(R.id.tv_hint);
if (Build.VERSION.SDK_INT >= 23) {
pb_loading.setIndeterminateTintList(getColorStateList(R.color.dialog_pro_color));
}
progressDialog = builder.create();
progressDialog.show();
return tv_hint;
}
public void closeProgressDialog() {
try {
if (progressDialog != null) {
progressDialog.dismiss();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (options.isFinger_zoom()) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = QRUtils.getInstance().getFingerSpacing(event);
break;
case MotionEvent.ACTION_MOVE:
if (event.getPointerCount() == 2) {
float newDist = QRUtils.getInstance().getFingerSpacing(event);
if (newDist > oldDist) {
cp.handleZoom(true);
} else if (newDist < oldDist) {
cp.handleZoom(false);
}
oldDist = newDist;
}
break;
}
}
return super.onTouchEvent(event);
}
@Override
public void onSensorChanged(SensorEvent event) {
float light = event.values[0];
if (light < AUTOLIGHTMIN) {//暂定值
if (cp.isPreviewStart()) {
cp.setFlash(true);
sensorManager.unregisterListener(this, sensor);
sensor = null;
sensorManager = null;
}
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
@@ -0,0 +1,76 @@
/*------------------------------------------------------------------------
* Config
*
* Copyright 2010 (c) Jeff Brown <spadix@users.sourceforge.net>
*
* This file is part of the ZBar Bar Code Reader.
*
* The ZBar Bar Code Reader is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* The ZBar Bar Code Reader is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with the ZBar Bar Code Reader; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* http://sourceforge.net/projects/zbar
*------------------------------------------------------------------------*/
package cn.bertsir.zbar.Qr;
/**
* Decoder configuration options.
*/
public class Config {
/**
* Enable symbology/feature.
*/
public static final int ENABLE = 0;
/**
* Enable check digit when optional.
*/
public static final int ADD_CHECK = 1;
/**
* Return check digit when present.
*/
public static final int EMIT_CHECK = 2;
/**
* Enable full ASCII character set.
*/
public static final int ASCII = 3;
/**
* Minimum data length for valid decode.
*/
public static final int MIN_LEN = 0x20;
/**
* Maximum data length for valid decode.
*/
public static final int MAX_LEN = 0x21;
/**
* Required video consistency frames.
*/
public static final int UNCERTAINTY = 0x40;
/**
* Enable scanner to collect position data.
*/
public static final int POSITION = 0x80;
/**
* Image scanner vertical scan density.
*/
public static final int X_DENSITY = 0x100;
/**
* Image scanner horizontal scan density.
*/
public static final int Y_DENSITY = 0x101;
}
@@ -0,0 +1,196 @@
/*------------------------------------------------------------------------
* Image
*
* Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
*
* This file is part of the ZBar Bar Code Reader.
*
* The ZBar Bar Code Reader is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* The ZBar Bar Code Reader is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with the ZBar Bar Code Reader; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* http://sourceforge.net/projects/zbar
*------------------------------------------------------------------------*/
package cn.bertsir.zbar.Qr;
/**
* stores image data samples along with associated format and size
* metadata.
*/
@SuppressWarnings("JniMissingFunction")
public class Image {
/**
* C pointer to a zbar_symbol_t.
*/
private long peer;
private Object data;
static {
System.loadLibrary("zbar");
init();
}
private static native void init();
public Image() {
peer = create();
}
public Image(int width, int height) {
this();
setSize(width, height);
}
public Image(int width, int height, String format) {
this();
setSize(width, height);
setFormat(format);
}
public Image(String format) {
this();
setFormat(format);
}
Image(long peer) {
this.peer = peer;
}
/**
* Create an associated peer instance.
*/
private native long create();
protected void finalize() {
destroy();
}
/**
* Clean up native data associated with an instance.
*/
public synchronized void destroy() {
if (peer != 0) {
destroy(peer);
peer = 0;
}
}
/**
* Destroy the associated peer instance.
*/
private native void destroy(long peer);
/**
* Image format conversion.
*
* @returns a @em new image with the sample data from the original
* image converted to the requested format fourcc. the original
* image is unaffected.
*/
public Image convert(String format) {
long newpeer = convert(peer, format);
if (newpeer == 0)
return (null);
return (new Image(newpeer));
}
private native long convert(long peer, String format);
/**
* Retrieve the image format fourcc.
*/
public native String getFormat();
/**
* Specify the fourcc image format code for image sample data.
*/
public native void setFormat(String format);
/**
* Retrieve a "sequence" (page/frame) number associated with this
* image.
*/
public native int getSequence();
/**
* Associate a "sequence" (page/frame) number with this image.
*/
public native void setSequence(int seq);
/**
* Retrieve the width of the image.
*/
public native int getWidth();
/**
* Retrieve the height of the image.
*/
public native int getHeight();
/**
* Retrieve the size of the image.
*/
public native int[] getSize();
/**
* Specify the pixel size of the image.
*/
public native void setSize(int width, int height);
/**
* Specify the pixel size of the image.
*/
public native void setSize(int[] size);
/**
* Retrieve the crop region of the image.
*/
public native int[] getCrop();
/**
* Specify the crop region of the image.
*/
public native void setCrop(int x, int y, int width, int height);
/**
* Specify the crop region of the image.
*/
public native void setCrop(int[] crop);
/**
* Retrieve the image sample data.
*/
public native byte[] getData();
/**
* Specify image sample data.
*/
public native void setData(byte[] data);
/**
* Specify image sample data.
*/
public native void setData(int[] data);
/**
* Retrieve the decoded results associated with this image.
*/
public SymbolSet getSymbols() {
return (new SymbolSet(getSymbols(peer)));
}
private native long getSymbols(long peer);
}
@@ -0,0 +1,111 @@
/*------------------------------------------------------------------------
* ImageScanner
*
* Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
*
* This file is part of the ZBar Bar Code Reader.
*
* The ZBar Bar Code Reader is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* The ZBar Bar Code Reader is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with the ZBar Bar Code Reader; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* http://sourceforge.net/projects/zbar
*------------------------------------------------------------------------*/
package cn.bertsir.zbar.Qr;
/**
* Read barcodes from 2-D images.
*/
@SuppressWarnings("JniMissingFunction")
public class ImageScanner {
/**
* C pointer to a zbar_image_scanner_t.
*/
private long peer;
static {
System.loadLibrary("zbar");
init();
}
private static native void init();
public ImageScanner() {
peer = create();
}
/**
* Create an associated peer instance.
*/
private native long create();
protected void finalize() {
destroy();
}
/**
* Clean up native data associated with an instance.
*/
public synchronized void destroy() {
if (peer != 0) {
destroy(peer);
peer = 0;
}
}
/**
* Destroy the associated peer instance.
*/
private native void destroy(long peer);
/**
* Set config for indicated symbology (0 for all) to specified value.
*/
public native void setConfig(int symbology, int config, int value)
throws IllegalArgumentException;
/**
* Parse configuration string and apply to image scanner.
*/
public native void parseConfig(String config);
/**
* Enable or disable the inter-image result cache (default disabled).
* Mostly useful for scanning video frames, the cache filters duplicate
* results from consecutive images, while adding some consistency
* checking and hysteresis to the results. Invoking this method also
* clears the cache.
*/
public native void enableCache(boolean enable);
/**
* Retrieve decode results for last scanned image.
*
* @returns the SymbolSet result container
*/
public SymbolSet getResults() {
return (new SymbolSet(getResults(peer)));
}
private native long getResults(long peer);
/**
* Scan for symbols in provided Image.
* The image format must currently be "Y800" or "GRAY".
*
* @returns the number of symbols successfully decoded from the image.
*/
public native int scanImage(Image image);
}
@@ -0,0 +1,44 @@
/*------------------------------------------------------------------------
* Modifier
*
* Copyright 2010 (c) Jeff Brown <spadix@users.sourceforge.net>
*
* This file is part of the ZBar Bar Code Reader.
*
* The ZBar Bar Code Reader is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* The ZBar Bar Code Reader is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with the ZBar Bar Code Reader; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* http://sourceforge.net/projects/zbar
*------------------------------------------------------------------------*/
package cn.bertsir.zbar.Qr;
/**
* Decoder symbology modifiers.
*/
public class Modifier {
/**
* barcode tagged as GS1 (EAN.UCC) reserved
* (eg, FNC1 before first data character).
* data may be parsed as a sequence of GS1 AIs
*/
public static final int GS1 = 0;
/**
* barcode tagged as AIM reserved
* (eg, FNC1 after first character or digit pair)
*/
public static final int AIM = 1;
}
@@ -0,0 +1,52 @@
/*------------------------------------------------------------------------
* Orientation
*
* Copyright 2010 (c) Jeff Brown <spadix@users.sourceforge.net>
*
* This file is part of the ZBar Bar Code Reader.
*
* The ZBar Bar Code Reader is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* The ZBar Bar Code Reader is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with the ZBar Bar Code Reader; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* http://sourceforge.net/projects/zbar
*------------------------------------------------------------------------*/
package cn.bertsir.zbar.Qr;
/**
* Decoded symbol coarse orientation.
*/
public class Orientation {
/**
* Unable to determine orientation.
*/
public static final int UNKNOWN = -1;
/**
* Upright, read left to right.
*/
public static final int UP = 0;
/**
* sideways, read top to bottom
*/
public static final int RIGHT = 1;
/**
* upside-down, read right to left
*/
public static final int DOWN = 2;
/**
* sideways, read bottom to top
*/
public static final int LEFT = 3;
}
@@ -0,0 +1,31 @@
package cn.bertsir.zbar.Qr;
/**
* Created by Bert on 2019-08-19.
* Mail: bertsir@163.com
*/
public class ScanResult {
public String content;
public int type;
public static final int CODE_QR = 1;//二维码
public static final int CODE_BAR = 2;//条形码
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}
@@ -0,0 +1,326 @@
/*------------------------------------------------------------------------
* Symbol
*
* Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
*
* This file is part of the ZBar Bar Code Reader.
*
* The ZBar Bar Code Reader is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* The ZBar Bar Code Reader is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with the ZBar Bar Code Reader; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* http://sourceforge.net/projects/zbar
*------------------------------------------------------------------------*/
package cn.bertsir.zbar.Qr;
/**
* Immutable container for decoded result symbols associated with an image
* or a composite symbol.
*/
@SuppressWarnings("JniMissingFunction")
public class Symbol {
/**
* No symbol decoded.
*/
public static final int NONE = 0;
/**
* Symbol detected but not decoded.
*/
public static final int PARTIAL = 1;
/**
* EAN-8.
*/
public static final int EAN8 = 8;
/**
* UPC-E.
*/
public static final int UPCE = 9;
/**
* ISBN-10 (from EAN-13).
*/
public static final int ISBN10 = 10;
/**
* UPC-A.
*/
public static final int UPCA = 12;
/**
* EAN-13.
*/
public static final int EAN13 = 13;
/**
* ISBN-13 (from EAN-13).
*/
public static final int ISBN13 = 14;
/**
* Interleaved 2 of 5.
*/
public static final int I25 = 25;
/**
* DataBar (RSS-14).
*/
public static final int DATABAR = 34;
/**
* DataBar Expanded.
*/
public static final int DATABAR_EXP = 35;
/**
* Codabar.
*/
public static final int CODABAR = 38;
/**
* Code 39.
*/
public static final int CODE39 = 39;
/**
* PDF417.
*/
public static final int PDF417 = 57;
/**
* QR Code.
*/
public static final int QRCODE = 64;
/**
* Code 93.
*/
public static final int CODE93 = 93;
/**
* Code 128.
*/
public static final int CODE128 = 128;
/**
* 裁剪的X轴
*/
public static int cropX = 0;
/**
* 裁剪的Y轴
*/
public static int cropY = 0;
/**
* 裁剪的宽
*/
public static int cropWidth = 0;
/**
* 裁剪的高
*/
public static int cropHeight = 0;
/**
* 屏幕的宽
*/
public static int screenWidth = 0;
/**
* 屏幕的高
*/
public static int screenHeight = 0;
/**
* 识别类型
*/
public static int scanType = 0;//1二维码 2UPCA条形码 3全部类型 4用户指定类型
/**
* 识别码类
*/
public static int scanFormat = 0;
/**
* 是否只识别框中内容
*/
public static boolean is_only_scan_center = false;
/**
* 是否自动拉近
*/
public static boolean is_auto_zoom = false;
/**
* 双识别引擎
*/
public static boolean doubleEngine = false;
/**
* 持续扫描
*/
public static boolean looperScan = false;
/**
* 持续扫描间隔时间
*/
public static int looperWaitTime = 0;
/**
* C pointer to a zbar_symbol_t.
*/
private long peer;
/**
* Cached attributes.
*/
private int type;
static {
System.loadLibrary("zbar");
init();
}
private static native void init();
/**
* Symbols are only created by other package methods.
*/
Symbol(long peer) {
this.peer = peer;
}
protected void finalize() {
destroy();
}
/**
* Clean up native data associated with an instance.
*/
public synchronized void destroy() {
if (peer != 0) {
destroy(peer);
peer = 0;
}
}
/**
* Release the associated peer instance.
*/
private native void destroy(long peer);
/**
* Retrieve type of decoded symbol.
*/
public int getType() {
if (type == 0)
type = getType(peer);
return (type);
}
private native int getType(long peer);
/**
* Retrieve symbology boolean configs settings used during decode.
*/
public native int getConfigMask();
/**
* Retrieve symbology characteristics detected during decode.
*/
public native int getModifierMask();
/**
* Retrieve data decoded from symbol as a String.
*/
public native String getData();
/**
* Retrieve raw data bytes decoded from symbol.
*/
public native byte[] getDataBytes();
/**
* Retrieve a symbol confidence metric. Quality is an unscaled,
* relative quantity: larger values are better than smaller
* values, where "large" and "small" are application dependent.
*/
public native int getQuality();
/**
* Retrieve current cache count. When the cache is enabled for
* the image_scanner this provides inter-frame reliability and
* redundancy information for video streams.
*
* @returns < 0 if symbol is still uncertain
* @returns 0 if symbol is newly verified
* @returns > 0 for duplicate symbols
*/
public native int getCount();
/**
* Retrieve an approximate, axis-aligned bounding box for the
* symbol.
*/
public int[] getBounds() {
int n = getLocationSize(peer);
if (n <= 0)
return (null);
int[] bounds = new int[4];
int xmin = Integer.MAX_VALUE;
int xmax = Integer.MIN_VALUE;
int ymin = Integer.MAX_VALUE;
int ymax = Integer.MIN_VALUE;
for (int i = 0; i < n; i++) {
int x = getLocationX(peer, i);
if (xmin > x) xmin = x;
if (xmax < x) xmax = x;
int y = getLocationY(peer, i);
if (ymin > y) ymin = y;
if (ymax < y) ymax = y;
}
bounds[0] = xmin;
bounds[1] = ymin;
bounds[2] = xmax - xmin;
bounds[3] = ymax - ymin;
return (bounds);
}
private native int getLocationSize(long peer);
private native int getLocationX(long peer, int idx);
private native int getLocationY(long peer, int idx);
public int[] getLocationPoint(int idx) {
int[] p = new int[2];
p[0] = getLocationX(peer, idx);
p[1] = getLocationY(peer, idx);
return (p);
}
/**
* Retrieve general axis-aligned, orientation of decoded
* symbol.
*/
public native int getOrientation();
/**
* Retrieve components of a composite result.
*/
public SymbolSet getComponents() {
return (new SymbolSet(getComponents(peer)));
}
private native long getComponents(long peer);
native long next();
}
@@ -0,0 +1,76 @@
/*------------------------------------------------------------------------
* SymbolIterator
*
* Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
*
* This file is part of the ZBar Bar Code Reader.
*
* The ZBar Bar Code Reader is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* The ZBar Bar Code Reader is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with the ZBar Bar Code Reader; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* http://sourceforge.net/projects/zbar
*------------------------------------------------------------------------*/
package cn.bertsir.zbar.Qr;
/**
* Iterator over a SymbolSet.
*/
public class SymbolIterator
implements java.util.Iterator<Symbol> {
/**
* Next symbol to be returned by the iterator.
*/
private Symbol current;
/**
* SymbolIterators are only created by internal interface methods.
*/
SymbolIterator(Symbol first) {
current = first;
}
/**
* Returns true if the iteration has more elements.
*/
public boolean hasNext() {
return (current != null);
}
/**
* Retrieves the next element in the iteration.
*/
public Symbol next() {
if (current == null)
throw (new java.util.NoSuchElementException
("access past end of SymbolIterator"));
Symbol result = current;
long sym = current.next();
if (sym != 0)
current = new Symbol(sym);
else
current = null;
return (result);
}
/**
* Raises UnsupportedOperationException.
*/
public void remove() {
throw (new UnsupportedOperationException
("SymbolIterator is immutable"));
}
}
@@ -0,0 +1,93 @@
/*------------------------------------------------------------------------
* SymbolSet
*
* Copyright 2007-2010 (c) Jeff Brown <spadix@users.sourceforge.net>
*
* This file is part of the ZBar Bar Code Reader.
*
* The ZBar Bar Code Reader is free software; you can redistribute it
* and/or modify it under the terms of the GNU Lesser Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* The ZBar Bar Code Reader is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser Public License for more details.
*
* You should have received a copy of the GNU Lesser Public License
* along with the ZBar Bar Code Reader; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*
* http://sourceforge.net/projects/zbar
*------------------------------------------------------------------------*/
package cn.bertsir.zbar.Qr;
/**
* Immutable container for decoded result symbols associated with an image
* or a composite symbol.
*/
@SuppressWarnings("JniMissingFunction")
public class SymbolSet
extends java.util.AbstractCollection<Symbol> {
/**
* C pointer to a zbar_symbol_set_t.
*/
private long peer;
static {
System.loadLibrary("zbar");
init();
}
private static native void init();
/**
* SymbolSets are only created by other package methods.
*/
SymbolSet(long peer) {
this.peer = peer;
}
protected void finalize() {
destroy();
}
/**
* Clean up native data associated with an instance.
*/
public synchronized void destroy() {
if (peer != 0) {
destroy(peer);
peer = 0;
}
}
/**
* Release the associated peer instance.
*/
private native void destroy(long peer);
/**
* Retrieve an iterator over the Symbol elements in this collection.
*/
public java.util.Iterator<Symbol> iterator() {
long sym = firstSymbol(peer);
if (sym == 0)
return (new SymbolIterator(null));
return (new SymbolIterator(new Symbol(sym)));
}
/**
* Retrieve the number of elements in the collection.
*/
public native int size();
/**
* Retrieve C pointer to first symbol in the set.
*/
private native long firstSymbol(long peer);
}
@@ -0,0 +1,445 @@
package cn.bertsir.zbar;
import android.graphics.Color;
import java.io.Serializable;
import androidx.annotation.DrawableRes;
import cn.bertsir.zbar.view.ScanLineView;
/**
* Created by Bert on 2017/9/22.
*/
public class QrConfig implements Serializable {
public static final int LINE_FAST = 1000;
public static final int LINE_MEDIUM = 2000;
public static final int LINE_SLOW = 3000;
public int CORNER_COLOR = Color.parseColor("#ff5f00");
public int LINE_COLOR = Color.parseColor("#ff5f00");
public int TITLE_BACKGROUND_COLOR = Color.parseColor("#ff5f00");
public int TITLE_TEXT_COLOR = Color.parseColor("#ffffff");
public boolean show_title = true;
public boolean show_light = true;
public boolean show_album = true;
public boolean show_des = true;
public boolean need_crop = true;
public boolean show_zoom = false;
public boolean auto_zoom = false;
public boolean finger_zoom = false;
public boolean only_center = false;
public boolean play_sound = true;
public boolean double_engine = false;
public boolean loop_scan = false;
public boolean show_vibrator = false;
public String title_text = "扫描二维码";
public String des_text = "(识别二维码)";
public String open_album_text = "选择要识别的图片";
public int line_speed = LINE_FAST;
public int line_style = ScanLineView.style_hybrid;
public int corner_width = 10;
public int loop_wait_time = 0;
// public int back_img_res = R.drawable.scanner_back_img;
public int back_img_res = R.drawable.top_back;
public int falsh_img_res = R.drawable.scanner_light;
public int album_img_res = R.drawable.scanner_album;
public boolean auto_light = false;
public static int ding_path = R.raw.qrcode;//默认声音
public int custombarcodeformat = -1;
public static final int TYPE_QRCODE = 1;//扫描二维码
public static final int TYPE_BARCODE = 2;//扫描条形码(UPCA)
public static final int TYPE_ALL = 3;//扫描全部类型码
public static final int TYPE_CUSTOM = 4;//扫描用户定义类型码
public static final int SCANVIEW_TYPE_QRCODE = 1;//二维码框
public static final int SCANVIEW_TYPE_BARCODE = 2;//条形码框
public static final int SCREEN_PORTRAIT = 1;//屏幕纵向
public static final int SCREEN_LANDSCAPE = 2;//屏幕横向
public static final int SCREEN_SENSOR = 3;//屏幕自动
public int scan_type = TYPE_QRCODE;//默认只扫描二维码
public int scan_view_type = SCANVIEW_TYPE_QRCODE;//默认为二维码扫描框
public final static int REQUEST_CAMERA = 99;
public final static String EXTRA_THIS_CONFIG = "extra_this_config";
public int SCREEN_ORIENTATION = SCREEN_PORTRAIT;
/**
* EAN-8.
*/
public static final int BARCODE_EAN8 = 8;
/**
* UPC-E.
*/
public static final int BARCODE_UPCE = 9;
/**
* ISBN-10 (from EAN-13).
*/
public static final int BARCODE_ISBN10 = 10;
/**
* UPC-A.
*/
public static final int BARCODE_UPCA = 12;
/**
* EAN-13.
*/
public static final int BARCODE_EAN13 = 13;
/**
* ISBN-13 (from EAN-13).
*/
public static final int BARCODE_ISBN13 = 14;
/**
* Interleaved 2 of 5.
*/
public static final int BARCODE_I25 = 25;
/**
* DataBar (RSS-14).
*/
public static final int BARCODE_DATABAR = 34;
/**
* DataBar Expanded.
*/
public static final int BARCODE_DATABAR_EXP = 35;
/**
* Codabar.
*/
public static final int BARCODE_CODABAR = 38;
/**
* Code 39.
*/
public static final int BARCODE_CODE39 = 39;
/**
* PDF417.
*/
public static final int BARCODE_PDF417 = 57;
/**
* Code 93.
*/
public static final int BARCODE_CODE93 = 93;
/**
* Code 128.
*/
public static final int BARCODE_CODE128 = 128;
public int getScan_type() {
return scan_type;
}
public boolean isPlay_sound() {
return play_sound;
}
public int getCORNER_COLOR() {
return CORNER_COLOR;
}
public int getLINE_COLOR() {
return LINE_COLOR;
}
public int getTITLE_BACKGROUND_COLOR() {
return TITLE_BACKGROUND_COLOR;
}
public int getTITLE_TEXT_COLOR() {
return TITLE_TEXT_COLOR;
}
public boolean isShow_title() {
return show_title;
}
public boolean isShow_light() {
return show_light;
}
public boolean isShow_album() {
return show_album;
}
public boolean isShow_des() {
return show_des;
}
public boolean isNeed_crop(){
return need_crop;
}
public String getTitle_text() {
return title_text;
}
public String getDes_text() {
return des_text;
}
public String getOpen_album_text() {
return open_album_text;
}
public int getLine_speed() {
return line_speed;
}
public int getLine_style() {
return line_style;
}
public int getCorner_width() {
return corner_width;
}
public int getCustombarcodeformat() {
return custombarcodeformat;
}
public int getScan_view_type() {
return scan_view_type;
}
public boolean isOnly_center() {
return only_center;
}
public static int getDing_path() {
return ding_path;
}
public boolean isShow_zoom() {
return show_zoom;
}
public boolean isAuto_zoom() {
return auto_zoom;
}
public boolean isFinger_zoom() {
return finger_zoom;
}
public int getSCREEN_ORIENTATION() {
return SCREEN_ORIENTATION;
}
public boolean isDouble_engine() {
return double_engine;
}
public boolean isLoop_scan() {
return loop_scan;
}
public int getLoop_wait_time() {
return loop_wait_time;
}
public boolean isAuto_light() {
return auto_light;
}
public boolean isShow_vibrator() {
return show_vibrator;
}
public int getBackImgRes(){ return back_img_res; }
public int getLightImageRes(){return falsh_img_res;}
public int getAblumImageRes(){ return album_img_res;}
public static class Builder{
private QrConfig watcher;
public Builder(){
watcher = new QrConfig();
}
public Builder setLineSpeed(int speed) {
watcher.line_speed = speed;
return this;
}
public Builder setLineColor(int color){
watcher.LINE_COLOR = color;
return this;
}
public Builder setCornerColor(int color){
watcher.CORNER_COLOR = color;
return this;
}
public Builder setCornerWidth(int dp){
watcher.corner_width = dp;
return this;
}
public Builder setDesText(String text){
watcher.des_text = text;
return this;
}
public Builder setTitleText(String text){
watcher.title_text = text;
return this;
}
public Builder setShowTitle(boolean show){
watcher.show_title = show;
return this;
}
public Builder setShowLight(boolean show){
watcher.show_light = show;
return this;
}
public Builder setShowAlbum(boolean show){
watcher.show_album = show;
return this;
}
public Builder setShowDes(boolean show){
watcher.show_des = show;
return this;
}
public Builder setNeedCrop(boolean crop){
watcher.need_crop = crop;
return this;
}
public Builder setTitleBackgroudColor(int color){
watcher.TITLE_BACKGROUND_COLOR = color;
return this;
}
public Builder setTitleTextColor(int color){
watcher.TITLE_TEXT_COLOR = color;
return this;
}
public Builder setScanType(int type){
watcher.scan_type = type;
return this;
}
public Builder setPlaySound(boolean play){
watcher.play_sound = play;
return this;
}
public Builder setCustombarcodeformat(int format){
watcher.custombarcodeformat = format;
return this;
}
public Builder setScanViewType(int type){
watcher.scan_view_type = type;
return this;
}
public Builder setIsOnlyCenter(boolean isOnlyCenter){
watcher.only_center = isOnlyCenter;
return this;
}
public Builder setDingPath(int ding){
watcher.ding_path = ding;
return this;
}
public Builder setShowZoom(boolean zoom){
watcher.show_zoom = zoom;
return this;
}
public Builder setAutoZoom(boolean auto){
watcher.auto_zoom = auto;
return this;
}
public Builder setFingerZoom(boolean auto){
watcher.finger_zoom = auto;
return this;
}
public Builder setScreenOrientation(int SCREEN_ORIENTATION) {
watcher.SCREEN_ORIENTATION = SCREEN_ORIENTATION;
return this;
}
public Builder setDoubleEngine(boolean open) {
watcher.double_engine = open;
return this;
}
public Builder setOpenAlbumText(String text) {
watcher.open_album_text = text;
return this;
}
public Builder setLooperScan(boolean looper){
watcher.loop_scan = looper;
return this;
}
public Builder setLooperWaitTime(int time){
watcher.loop_wait_time = time;
return this;
}
public Builder setScanLineStyle(int style){
watcher.line_style = style;
return this;
}
public Builder setAutoLight(boolean light){
watcher.auto_light = light;
return this;
}
public Builder setShowVibrator(boolean vibrator){
watcher.show_vibrator = vibrator;
return this;
}
public Builder setBackImageRes(@DrawableRes int res){
watcher.back_img_res = res;
return this;
}
public Builder setLightImageRes(@DrawableRes int res){
watcher.falsh_img_res = res;
return this;
}
public Builder setAblumImageRes(@DrawableRes int res){
watcher.album_img_res = res;
return this;
}
public QrConfig create(){
return watcher;
}
}
}
@@ -0,0 +1,88 @@
package cn.bertsir.zbar;
import android.app.Activity;
import android.content.Intent;
import android.widget.Toast;
import java.util.List;
import cn.bertsir.zbar.Qr.ScanResult;
import cn.bertsir.zbar.utils.PermissionConstants;
import cn.bertsir.zbar.utils.PermissionUtils;
/**
* Created by Bert on 2017/9/22.
*/
public class QrManager {
private static QrManager instance;
private QrConfig options;
public OnScanResultCallback resultCallback;
public synchronized static QrManager getInstance() {
if(instance == null)
instance = new QrManager();
return instance;
}
public OnScanResultCallback getResultCallback() {
return resultCallback;
}
public QrManager init(QrConfig options) {
this.options = options;
return this;
}
public void startScan(final Activity activity, OnScanResultCallback resultCall){
if (options == null) {
options = new QrConfig.Builder().create();
}
PermissionUtils.permission(activity, PermissionConstants.CAMERA,PermissionConstants.STORAGE)
.rationale(new PermissionUtils.OnRationaleListener() {
@Override
public void rationale(final ShouldRequest shouldRequest) {
shouldRequest.again(true);
}
})
.callback(new PermissionUtils.FullCallback() {
@Override
public void onGranted(List<String> permissionsGranted) {
Intent intent = new Intent(activity, QRActivity.class);
intent.putExtra(QrConfig.EXTRA_THIS_CONFIG, options);
activity.startActivity(intent);
}
@Override
public void onDenied(List<String> permissionsDeniedForever,
List<String> permissionsDenied) {
Toast.makeText(activity,"摄像头权限被拒绝!",Toast.LENGTH_SHORT).show();
}
}).request();
// 绑定图片接口回调函数事件
resultCallback = resultCall;
}
public interface OnScanResultCallback {
/**
* 处理成功
* 多选
*
* @param result
*/
void onScanSuccess(ScanResult result);
}
}
@@ -0,0 +1,31 @@
/*
* Copyright © Yan Zhenjie
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.bertsir.zbar;
import cn.bertsir.zbar.Qr.ScanResult;
/**
* <p>Scan results callback.</p>
*/
public interface ScanCallback {
/**
* 扫描结果回调
*
*/
void onScanResult(ScanResult result);
}
@@ -0,0 +1,133 @@
package cn.bertsir.zbar.utils;
import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
/**
* Created by Bert on 2018/9/5.
*/
public class GetPathFromUri {
@SuppressLint("NewApi")
public static String getPath(final Context context, final Uri uri) {
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
if ("primary".equalsIgnoreCase(type)) {
return Environment.getExternalStorageDirectory() + "/" + split[1];
}
// TODO handle non-primary volumes
}
// DownloadsProvider
else if (isDownloadsDocument(uri)) {
final String id = DocumentsContract.getDocumentId(uri);
final Uri contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
}
// MediaProvider
else if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
final String selection = "_id=?";
final String[] selectionArgs = new String[]{split[1]};
return getDataColumn(context, contentUri, selection, selectionArgs);
}
}
// MediaStore (and general)
else if ("content".equalsIgnoreCase(uri.getScheme())) {
return getDataColumn(context, uri, null, null);
}
// File
else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
}
/**
* Get the value of the data column for this Uri. This is useful for
* MediaStore Uris, and other file-based ContentProviders.
*
* @param context The context.
* @param uri The Uri to query.
* @param selection (Optional) Filter used in the query.
* @param selectionArgs (Optional) Selection arguments used in the query.
* @return The value of the _data column, which is typically a file path.
*/
public static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {column};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if (cursor != null && cursor.moveToFirst()) {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
}
} finally {
if (cursor != null)
cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
public static boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
public static boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
public static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
}
@@ -0,0 +1,91 @@
package cn.bertsir.zbar.utils;
import android.Manifest;
import android.Manifest.permission;
import android.annotation.SuppressLint;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* <pre>
* author: Blankj
* blog : http://blankj.com
* time : 2017/12/29
* desc : constants of permission
* </pre>
*/
@SuppressLint("InlinedApi")
public final class PermissionConstants {
public static final String CALENDAR = Manifest.permission_group.CALENDAR;
public static final String CAMERA = Manifest.permission_group.CAMERA;
public static final String CONTACTS = Manifest.permission_group.CONTACTS;
public static final String LOCATION = Manifest.permission_group.LOCATION;
public static final String MICROPHONE = Manifest.permission_group.MICROPHONE;
public static final String PHONE = Manifest.permission_group.PHONE;
public static final String SENSORS = Manifest.permission_group.SENSORS;
public static final String SMS = Manifest.permission_group.SMS;
public static final String STORAGE = Manifest.permission_group.STORAGE;
private static final String[] GROUP_CALENDAR = {
permission.READ_CALENDAR, permission.WRITE_CALENDAR
};
private static final String[] GROUP_CAMERA = {
permission.CAMERA
};
private static final String[] GROUP_CONTACTS = {
permission.READ_CONTACTS, permission.WRITE_CONTACTS, permission.GET_ACCOUNTS
};
private static final String[] GROUP_LOCATION = {
permission.ACCESS_FINE_LOCATION, permission.ACCESS_COARSE_LOCATION
};
private static final String[] GROUP_MICROPHONE = {
permission.RECORD_AUDIO
};
private static final String[] GROUP_PHONE = {
permission.READ_PHONE_STATE, permission.CALL_PHONE
, permission.READ_CALL_LOG, permission.WRITE_CALL_LOG,
permission.ADD_VOICEMAIL, permission.USE_SIP, permission.PROCESS_OUTGOING_CALLS
};
private static final String[] GROUP_SENSORS = {
permission.BODY_SENSORS
};
private static final String[] GROUP_SMS = {
permission.SEND_SMS, permission.RECEIVE_SMS, permission.READ_SMS,
permission.RECEIVE_WAP_PUSH, permission.RECEIVE_MMS,
};
private static final String[] GROUP_STORAGE = {
permission.READ_EXTERNAL_STORAGE, permission.WRITE_EXTERNAL_STORAGE
};
//@StringDef({CALENDAR, CAMERA, CONTACTS, LOCATION, MICROPHONE, PHONE, SENSORS, SMS, STORAGE,})
@Retention(RetentionPolicy.SOURCE)
public @interface Permission {
}
public static String[] getPermissions(@Permission final String permission) {
switch (permission) {
case CALENDAR:
return GROUP_CALENDAR;
case CAMERA:
return GROUP_CAMERA;
case CONTACTS:
return GROUP_CONTACTS;
case LOCATION:
return GROUP_LOCATION;
case MICROPHONE:
return GROUP_MICROPHONE;
case PHONE:
return GROUP_PHONE;
case SENSORS:
return GROUP_SENSORS;
case SMS:
return GROUP_SMS;
case STORAGE:
return GROUP_STORAGE;
}
return new String[]{permission};
}
}
@@ -0,0 +1,369 @@
package cn.bertsir.zbar.utils;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.WindowManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.content.ContextCompat;
/**
* <pre>
* author: Blankj
* blog : http://blankj.com
* time : 2017/12/29
* desc : utils about permission
* </pre>
*/
public final class PermissionUtils {
private static List<String> PERMISSIONS = null;
private static PermissionUtils sInstance;
private OnRationaleListener mOnRationaleListener;
private SimpleCallback mSimpleCallback;
private FullCallback mFullCallback;
private ThemeCallback mThemeCallback;
private Set<String> mPermissions;
private List<String> mPermissionsRequest;
private List<String> mPermissionsGranted;
private List<String> mPermissionsDenied;
private List<String> mPermissionsDeniedForever;
private static Context mApp;
/**
* Return the permissions used in application.
*
* @return the permissions used in application
*/
public static List<String> getPermissions() {
return getPermissions(mApp.getPackageName());
}
/**
* Return the permissions used in application.
*
* @param packageName The name of the package.
* @return the permissions used in application
*/
public static List<String> getPermissions(final String packageName) {
PackageManager pm = mApp.getPackageManager();
try {
return Arrays.asList(
pm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS)
.requestedPermissions
);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
return Collections.emptyList();
}
}
/**
* Return whether <em>you</em> have granted the permissions.
*
* @param permissions The permissions.
* @return {@code true}: yes<br>{@code false}: no
*/
public static boolean isGranted(final String... permissions) {
for (String permission : permissions) {
if (!isGranted(permission)) {
return false;
}
}
return true;
}
private static boolean isGranted(final String permission) {
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M
|| PackageManager.PERMISSION_GRANTED
== ContextCompat.checkSelfPermission(mApp, permission);
}
/**
* Launch the application's details settings.
*/
public static void launchAppDetailsSettings() {
Intent intent = new Intent("android.settings.APPLICATION_DETAILS_SETTINGS");
intent.setData(Uri.parse("package:" + mApp.getPackageName()));
mApp.startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
/**
* Set the permissions.
*
* @param permissions The permissions.
* @return the single {@link PermissionUtils} instance
*/
public static PermissionUtils permission(Context mContext, @PermissionConstants.Permission final String...
permissions
) {
mApp = mContext;
PERMISSIONS = getPermissions();
return new PermissionUtils(permissions);
}
private PermissionUtils(final String... permissions) {
mPermissions = new LinkedHashSet<>();
for (String permission : permissions) {
for (String aPermission : PermissionConstants.getPermissions(permission)) {
if (PERMISSIONS.contains(aPermission)) {
mPermissions.add(aPermission);
}
}
}
sInstance = this;
}
/**
* Set rationale listener.
*
* @param listener The rationale listener.
* @return the single {@link PermissionUtils} instance
*/
public PermissionUtils rationale(final OnRationaleListener listener) {
mOnRationaleListener = listener;
return this;
}
/**
* Set the simple call back.
*
* @param callback the simple call back
* @return the single {@link PermissionUtils} instance
*/
public PermissionUtils callback(final SimpleCallback callback) {
mSimpleCallback = callback;
return this;
}
/**
* Set the full call back.
*
* @param callback the full call back
* @return the single {@link PermissionUtils} instance
*/
public PermissionUtils callback(final FullCallback callback) {
mFullCallback = callback;
return this;
}
/**
* Set the theme callback.
*
* @param callback The theme callback.
* @return the single {@link PermissionUtils} instance
*/
public PermissionUtils theme(final ThemeCallback callback) {
mThemeCallback = callback;
return this;
}
/**
* Start request.
*/
public void request() {
mPermissionsGranted = new ArrayList<>();
mPermissionsRequest = new ArrayList<>();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
mPermissionsGranted.addAll(mPermissions);
requestCallback();
} else {
for (String permission : mPermissions) {
if (isGranted(permission)) {
mPermissionsGranted.add(permission);
} else {
mPermissionsRequest.add(permission);
}
}
if (mPermissionsRequest.isEmpty()) {
requestCallback();
} else {
startPermissionActivity();
}
}
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void startPermissionActivity() {
mPermissionsDenied = new ArrayList<>();
mPermissionsDeniedForever = new ArrayList<>();
PermissionActivity.start(mApp);
}
@RequiresApi(api = Build.VERSION_CODES.M)
private boolean rationale(final Activity activity) {
boolean isRationale = false;
if (mOnRationaleListener != null) {
for (String permission : mPermissionsRequest) {
if (activity.shouldShowRequestPermissionRationale(permission)) {
getPermissionsStatus(activity);
mOnRationaleListener.rationale(new OnRationaleListener.ShouldRequest() {
@Override
public void again(boolean again) {
if (again) {
startPermissionActivity();
} else {
requestCallback();
}
}
});
isRationale = true;
break;
}
}
mOnRationaleListener = null;
}
return isRationale;
}
private void getPermissionsStatus(final Activity activity) {
for (String permission : mPermissionsRequest) {
if (isGranted(permission)) {
mPermissionsGranted.add(permission);
} else {
mPermissionsDenied.add(permission);
if (!activity.shouldShowRequestPermissionRationale(permission)) {
mPermissionsDeniedForever.add(permission);
}
}
}
}
private void requestCallback() {
if (mSimpleCallback != null) {
if (mPermissionsRequest.size() == 0
|| mPermissions.size() == mPermissionsGranted.size()) {
mSimpleCallback.onGranted();
} else {
if (!mPermissionsDenied.isEmpty()) {
mSimpleCallback.onDenied();
}
}
mSimpleCallback = null;
}
if (mFullCallback != null) {
if (mPermissionsRequest.size() == 0
|| mPermissions.size() == mPermissionsGranted.size()) {
mFullCallback.onGranted(mPermissionsGranted);
} else {
if (!mPermissionsDenied.isEmpty()) {
mFullCallback.onDenied(mPermissionsDeniedForever, mPermissionsDenied);
}
}
mFullCallback = null;
}
mOnRationaleListener = null;
mThemeCallback = null;
}
private void onRequestPermissionsResult(final Activity activity) {
getPermissionsStatus(activity);
requestCallback();
}
@RequiresApi(api = Build.VERSION_CODES.M)
public static class PermissionActivity extends Activity {
public static void start(final Context context) {
Intent starter = new Intent(context, PermissionActivity.class);
starter.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(starter);
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
getWindow().setStatusBarColor(Color.TRANSPARENT);
if (sInstance == null) {
super.onCreate(savedInstanceState);
Log.e("PermissionUtils", "request permissions failed");
finish();
return;
}
if (sInstance.mThemeCallback != null) {
sInstance.mThemeCallback.onActivityCreate(this);
}
super.onCreate(savedInstanceState);
if (sInstance.rationale(this)) {
finish();
return;
}
if (sInstance.mPermissionsRequest != null) {
int size = sInstance.mPermissionsRequest.size();
if (size <= 0) {
finish();
return;
}
requestPermissions(sInstance.mPermissionsRequest.toArray(new String[size]), 1);
}
}
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults) {
sInstance.onRequestPermissionsResult(this);
finish();
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
finish();
return true;
}
}
///////////////////////////////////////////////////////////////////////////
// interface
///////////////////////////////////////////////////////////////////////////
public interface OnRationaleListener {
void rationale(ShouldRequest shouldRequest);
interface ShouldRequest {
void again(boolean again);
}
}
public interface SimpleCallback {
void onGranted();
void onDenied();
}
public interface FullCallback {
void onGranted(List<String> permissionsGranted);
void onDenied(List<String> permissionsDeniedForever, List<String> permissionsDenied);
}
public interface ThemeCallback {
void onActivityCreate(Activity activity);
}
}
@@ -0,0 +1,670 @@
package cn.bertsir.zbar.utils;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.drawable.BitmapDrawable;
import android.os.Build;
import android.os.Vibrator;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.ChecksumException;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.FormatException;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.RGBLuminanceSource;
import com.google.zxing.Result;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.GlobalHistogramBinarizer;
import com.google.zxing.qrcode.QRCodeReader;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.io.File;
import java.util.Hashtable;
import cn.bertsir.zbar.Qr.Config;
import cn.bertsir.zbar.Qr.Image;
import cn.bertsir.zbar.Qr.ImageScanner;
import cn.bertsir.zbar.Qr.Symbol;
import cn.bertsir.zbar.Qr.SymbolSet;
/**
* Created by Bert on 2017/9/20.
*/
public class QRUtils {
private static QRUtils instance;
private Bitmap scanBitmap;
private Context mContext;
public static QRUtils getInstance() {
if (instance == null) {
instance = new QRUtils();
}
return instance;
}
/**
* 识别本地二维码
*
* @param path
* @return
*/
public String decodeQRcode(String path) throws Exception {
//对图片进行灰度处理,为了兼容彩色二维码
Bitmap qrbmp = compressImage(path);
qrbmp = toGrayscale(qrbmp);
if (qrbmp != null) {
return decodeQRcode(qrbmp);
} else {
return "";
}
}
public String decodeQRcode(ImageView iv) throws Exception {
Bitmap qrbmp = ((BitmapDrawable) (iv).getDrawable()).getBitmap();
if (qrbmp != null) {
return decodeQRcode(qrbmp);
} else {
return "";
}
}
public String decodeQRcode(Bitmap barcodeBmp) throws Exception {
int width = barcodeBmp.getWidth();
int height = barcodeBmp.getHeight();
int[] pixels = new int[width * height];
barcodeBmp.getPixels(pixels, 0, width, 0, 0, width, height);
Image barcode = new Image(width, height, "RGB4");
barcode.setData(pixels);
ImageScanner reader = new ImageScanner();
reader.setConfig(Symbol.NONE, Config.ENABLE, 0);
reader.setConfig(Symbol.QRCODE, Config.ENABLE, 1);
int result = reader.scanImage(barcode.convert("Y800"));
String qrCodeString = null;
if (result != 0) {
SymbolSet syms = reader.getResults();
for (Symbol sym : syms) {
qrCodeString = sym.getData();
}
}
barcodeBmp.recycle();
return qrCodeString;
}
/**
* 扫描二维码图片的方法
* @param path
* @return
*/
public String decodeQRcodeByZxing(String path) {
if (TextUtils.isEmpty(path)) {
return null;
}
Hashtable<DecodeHintType, String> hints = new Hashtable();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); // 设置二维码内容的编码
Bitmap scanBitmap = compressImage(path);
int[] data = new int[scanBitmap.getWidth() * scanBitmap.getHeight()];
scanBitmap.getPixels(data, 0, scanBitmap.getWidth(), 0, 0, scanBitmap.getWidth(), scanBitmap.getHeight());
RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(scanBitmap.getWidth(),scanBitmap.getHeight(),data);
BinaryBitmap binaryBitmap = new BinaryBitmap(new GlobalHistogramBinarizer(rgbLuminanceSource));
QRCodeReader reader = new QRCodeReader();
Result result = null;
try {
result = reader.decode(binaryBitmap, hints);
} catch (NotFoundException e) {
}catch (ChecksumException e){
}catch(FormatException e){
}
if(result == null){
return "";
}else {
return result.getText();
}
}
/**
* 扫描二维码图片的方法
* @return
*/
public String decodeQRcodeByZxing(Bitmap bitmap) {
Hashtable<DecodeHintType, String> hints = new Hashtable();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); // 设置二维码内容的编码
scanBitmap =bitmap;
int[] data = new int[scanBitmap.getWidth() * scanBitmap.getHeight()];
scanBitmap.getPixels(data, 0, scanBitmap.getWidth(), 0, 0, scanBitmap.getWidth(), scanBitmap.getHeight());
RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(scanBitmap.getWidth(),scanBitmap.getHeight(),data);
BinaryBitmap binaryBitmap = new BinaryBitmap(new GlobalHistogramBinarizer(rgbLuminanceSource));
QRCodeReader reader = new QRCodeReader();
Result result = null;
try {
result = reader.decode(binaryBitmap, hints);
} catch (NotFoundException e) {
}catch (ChecksumException e){
}catch(FormatException e){
}
if(result == null){
return "";
}else {
return result.getText();
}
}
/**
* 识别本地条形码
*
* @param url
* @return
*/
public String decodeBarcode(String url) {
Bitmap qrbmp = BitmapFactory.decodeFile(url);
if (qrbmp != null) {
return decodeBarcode(qrbmp);
} else {
return "";
}
}
public String decodeBarcode(ImageView iv) {
Bitmap qrbmp = ((BitmapDrawable) (iv).getDrawable()).getBitmap();
if (qrbmp != null) {
return decodeBarcode(qrbmp);
} else {
return "";
}
}
public String decodeBarcode(Bitmap barcodeBmp) {
int width = barcodeBmp.getWidth();
int height = barcodeBmp.getHeight();
int[] pixels = new int[width * height];
barcodeBmp.getPixels(pixels, 0, width, 0, 0, width, height);
Image barcode = new Image(width, height, "RGB4");
barcode.setData(pixels);
ImageScanner reader = new ImageScanner();
reader.setConfig(Symbol.NONE, Config.ENABLE, 0);
reader.setConfig(Symbol.CODE128, Config.ENABLE, 1);
reader.setConfig(Symbol.CODE39, Config.ENABLE, 1);
reader.setConfig(Symbol.EAN13, Config.ENABLE, 1);
reader.setConfig(Symbol.EAN8, Config.ENABLE, 1);
reader.setConfig(Symbol.UPCA, Config.ENABLE, 1);
reader.setConfig(Symbol.UPCE, Config.ENABLE, 1);
int result = reader.scanImage(barcode.convert("Y800"));
String qrCodeString = null;
if (result != 0) {
SymbolSet syms = reader.getResults();
for (Symbol sym : syms) {
qrCodeString = sym.getData();
}
}
return qrCodeString;
}
/**
* 生成二维码
*
* @param content
* @return
*/
public Bitmap createQRCode(String content) {
return createQRCode(content, 300, 300);
}
/**
* 生成二维码
*
* @param content
* @return
*/
public Bitmap createQRCode(String content, int width, int height) {
Bitmap bitmap = null;
BitMatrix result = null;
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
try {
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);//这里调整二维码的容错率
hints.put(EncodeHintType.MARGIN, 1); //设置白边取值1-4,值越大白边越大
result = multiFormatWriter.encode(new String(content.getBytes("UTF-8"), "ISO-8859-1"), BarcodeFormat
.QR_CODE, width, height, hints);
int w = result.getWidth();
int h = result.getHeight();
int[] pixels = new int[w * h];
for (int y = 0; y < h; y++) {
int offset = y * w;
for (int x = 0; x < w; x++) {
pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.WHITE;
}
}
bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, w, 0, 0, w, h);
} catch (Exception e) {
e.printStackTrace();
}
return bitmap;
}
/**
* 生成带logo的二维码
*
* @param content
* @param logo
* @return
*/
public Bitmap createQRCodeAddLogo(String content, Bitmap logo) {
Bitmap qrCode = createQRCode(content);
int qrheight = qrCode.getHeight();
int qrwidth = qrCode.getWidth();
int waterWidth = (int) (qrwidth * 0.3);//0.3为logo占二维码大小的倍数 建议不要过大,否则二维码失效
float scale = waterWidth / (float) logo.getWidth();
Bitmap waterQrcode = createWaterMaskCenter(qrCode, zoomImg(logo, scale));
return waterQrcode;
}
public Bitmap createQRCodeAddLogo(String content, int width, int height, Bitmap logo) {
Bitmap qrCode = createQRCode(content, width, height);
int qrheight = qrCode.getHeight();
int qrwidth = qrCode.getWidth();
int waterWidth = (int) (qrwidth * 0.3);//0.3为logo占二维码大小的倍数 建议不要过大,否则二维码失效
float scale = waterWidth / (float) logo.getWidth();
Bitmap waterQrcode = createWaterMaskCenter(qrCode, zoomImg(logo, scale));
return waterQrcode;
}
/**
* 生成条形码
*
* @param context
* @param contents
* @param desiredWidth
* @param desiredHeight
* @return
*/
@Deprecated
public Bitmap createBarcode(Context context, String contents, int desiredWidth, int desiredHeight) {
if (TextUtils.isEmpty(contents)) {
throw new NullPointerException("contents not be null");
}
if (desiredWidth == 0 || desiredHeight == 0) {
throw new NullPointerException("desiredWidth or desiredHeight not be null");
}
Bitmap resultBitmap;
/**
* 条形码的编码类型
*/
BarcodeFormat barcodeFormat = BarcodeFormat.CODE_128;
resultBitmap = encodeAsBitmap(contents, barcodeFormat,
desiredWidth, desiredHeight);
return resultBitmap;
}
/**
* 生成条形码
*
* @param context
* @param contents
* @param desiredWidth
* @param desiredHeight
* @return
*/
public Bitmap createBarCodeWithText(Context context, String contents, int desiredWidth,
int desiredHeight) {
return createBarCodeWithText(context, contents, desiredWidth, desiredHeight, null);
}
public Bitmap createBarCodeWithText(Context context, String contents, int desiredWidth,
int desiredHeight, TextViewConfig config) {
if (TextUtils.isEmpty(contents)) {
throw new NullPointerException("contents not be null");
}
if (desiredWidth == 0 || desiredHeight == 0) {
throw new NullPointerException("desiredWidth or desiredHeight not be null");
}
Bitmap resultBitmap;
/**
* 条形码的编码类型
*/
BarcodeFormat barcodeFormat = BarcodeFormat.CODE_128;
Bitmap barcodeBitmap = encodeAsBitmap(contents, barcodeFormat,
desiredWidth, desiredHeight);
Bitmap codeBitmap = createCodeBitmap(contents, barcodeBitmap.getWidth(),
barcodeBitmap.getHeight(), context, config);
resultBitmap = mixtureBitmap(barcodeBitmap, codeBitmap, new PointF(
0, desiredHeight));
return resultBitmap;
}
private Bitmap encodeAsBitmap(String contents, BarcodeFormat format, int desiredWidth, int desiredHeight) {
final int WHITE = 0xFFFFFFFF;
final int BLACK = 0xFF000000;
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix result = null;
try {
result = writer.encode(contents, format, desiredWidth,
desiredHeight, null);
} catch (WriterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int width = result.getWidth();
int height = result.getHeight();
int[] pixels = new int[width * height];
// All are 0, or black, by default
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) {
pixels[offset + x] = result.get(x, y) ? BLACK : WHITE;
}
}
Bitmap bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
private Bitmap createCodeBitmap(String contents, int width, int height, Context context,
TextViewConfig config) {
if (config == null) {
config = new TextViewConfig();
}
TextView tv = new TextView(context);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
tv.setLayoutParams(layoutParams);
tv.setText(contents);
tv.setTextSize(config.size == 0 ? tv.getTextSize() : config.size);
tv.setHeight(height);
tv.setGravity(config.gravity);
tv.setMaxLines(config.maxLines);
tv.setWidth(width);
tv.setDrawingCacheEnabled(true);
tv.setTextColor(config.color);
tv.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
tv.layout(0, 0, tv.getMeasuredWidth(), tv.getMeasuredHeight());
tv.buildDrawingCache();
return tv.getDrawingCache();
}
public static class TextViewConfig {
private int gravity = Gravity.CENTER;
private int maxLines = 1;
private int color = Color.BLACK;
private float size;
public TextViewConfig() {
}
public void setGravity(int gravity) {
this.gravity = gravity;
}
public void setMaxLines(int maxLines) {
this.maxLines = maxLines;
}
public void setColor(int color) {
this.color = color;
}
public void setSize(float size) {
this.size = size;
}
}
/**
* 将两个Bitmap合并成一个
*
* @param first
* @param second
* @param fromPoint 第二个Bitmap开始绘制的起始位置(相对于第一个Bitmap)
* @return
*/
private Bitmap mixtureBitmap(Bitmap first, Bitmap second, PointF fromPoint) {
if (first == null || second == null || fromPoint == null) {
return null;
}
int width = Math.max(first.getWidth(), second.getWidth());
Bitmap newBitmap = Bitmap.createBitmap(
width,
first.getHeight() + second.getHeight(), Bitmap.Config.ARGB_4444);
Canvas cv = new Canvas(newBitmap);
cv.drawBitmap(first, 0, 0, null);
cv.drawBitmap(second, fromPoint.x, fromPoint.y, null);
cv.save(Canvas.ALL_SAVE_FLAG);
cv.restore();
return newBitmap;
}
/**
* 设置水印图片到中间
*
* @param src
* @param watermark
* @return
*/
private Bitmap createWaterMaskCenter(Bitmap src, Bitmap watermark) {
return createWaterMaskBitmap(src, watermark,
(src.getWidth() - watermark.getWidth()) / 2,
(src.getHeight() - watermark.getHeight()) / 2);
}
private Bitmap createWaterMaskBitmap(Bitmap src, Bitmap watermark, int paddingLeft, int paddingTop) {
if (src == null) {
return null;
}
int width = src.getWidth();
int height = src.getHeight();
Bitmap newb = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图
Canvas canvas = new Canvas(newb);
canvas.drawBitmap(src, 0, 0, null);
canvas.drawBitmap(watermark, paddingLeft, paddingTop, null);
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
return newb;
}
/**
* 缩放Bitmap
*
* @param bm
* @param f
* @return
*/
private Bitmap zoomImg(Bitmap bm, float f) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = f;
float scaleHeight = f;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
return newbm;
}
public boolean isMIUI() {
String manufacturer = Build.MANUFACTURER;
if ("xiaomi".equalsIgnoreCase(manufacturer)) {
return true;
}
return false;
}
/**
* Return the width of screen, in pixel.
*
* @return the width of screen, in pixel
*/
public int getScreenWidth(Context mContext) {
WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
Point point = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
//noinspection ConstantConditions
wm.getDefaultDisplay().getRealSize(point);
} else {
//noinspection ConstantConditions
wm.getDefaultDisplay().getSize(point);
}
return point.x;
}
/**
* Return the height of screen, in pixel.
*
* @return the height of screen, in pixel
*/
public int getScreenHeight(Context mContext) {
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Point point = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
//noinspection ConstantConditions
wm.getDefaultDisplay().getRealSize(point);
} else {
//noinspection ConstantConditions
wm.getDefaultDisplay().getSize(point);
}
return point.y;
}
/**
* 返回当前屏幕是否为竖屏。
* @param context
* @return 当且仅当当前屏幕为竖屏时返回true,否则返回false。
*/
public boolean isScreenOriatationPortrait(Context context) {
return context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
}
public float getFingerSpacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.sqrt(x * x + y * y);
}
/**
* 对bitmap进行灰度处理
* @param bmpOriginal
* @return
*/
private Bitmap toGrayscale(Bitmap bmpOriginal) {
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
/**
* 压缩图片
* @param path
* @return
*/
private Bitmap compressImage(String path){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true; // 先获取原大小
scanBitmap = BitmapFactory.decodeFile(path,options);
options.inJustDecodeBounds = false;
int sampleSizeH = (int) (options.outHeight / (float) 800);
int sampleSizeW = (int) (options.outWidth / (float) 800);
int sampleSize = Math.max(sampleSizeH,sampleSizeW);
if (sampleSize <= 0) {
sampleSize = 1;
}
options.inSampleSize = sampleSize;
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap qrbmp = BitmapFactory.decodeFile(path,options);
return qrbmp;
}
public boolean deleteTempFile(String delFile) {
File file = new File(delFile);
if (file.exists() && file.isFile()) {
if (file.delete()) {
return true;
} else {
return false;
}
} else {
return false;
}
}
//震动提醒
public void getVibrator(Context mContext){
Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
long[] pattern = {0, 50, 0, 0};
vibrator.vibrate(pattern, -1);
}
}
@@ -0,0 +1,11 @@
package cn.bertsir.zbar.utils;
import androidx.core.content.FileProvider;
/**
* Created by Bert on 2019/3/4.
* Mail: bertsir@163.com
*/
public class QrFileProvider extends FileProvider {
}
@@ -0,0 +1,109 @@
package cn.bertsir.zbar.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import cn.bertsir.zbar.R;
/**
* Created by Bert on 2017/9/22.
*/
public class CornerView extends View {
private Paint paint;//声明画笔
private Canvas canvas;//画布
private static final String TAG = "CornerView";
private int width = 0;
private int height = 0;
private int cornerColor;
private int cornerWidth;
private int cornerGravity;
private static final int LEFT_TOP = 0;
private static final int LEFT_BOTTOM = 1;
private static final int RIGHT_TOP = 2;
private static final int RIGHT_BOTTOM = 3;
public CornerView(Context context) {
super(context,null);
}
public CornerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CornerView);
cornerColor = a.getColor(R.styleable.CornerView_corner_color, getResources().getColor(R.color.common_color));
cornerWidth = (int) a.getDimension(R.styleable.CornerView_corner_width, 10);
cornerGravity = a.getInt(R.styleable.CornerView_corner_gravity, 1);
a.recycle();
paint=new Paint();//创建一个画笔
canvas=new Canvas();
paint.setStyle(Paint.Style.FILL);//设置非填充
paint.setStrokeWidth(cornerWidth);//笔宽5像素
paint.setColor(cornerColor);//设置为红笔
paint.setAntiAlias(true);//锯齿不显示
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getMeasuredWidth();
height = getMeasuredHeight();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (cornerGravity){
case LEFT_TOP:
canvas.drawLine(0, 0, width, 0, paint);
canvas.drawLine(0, 0, 0, height, paint);
break;
case LEFT_BOTTOM:
canvas.drawLine(0, 0, 0, height, paint);
canvas.drawLine(0, height, width, height, paint);
break;
case RIGHT_TOP:
canvas.drawLine(0, 0, width, 0, paint);
canvas.drawLine(width, 0, width, height, paint);
break;
case RIGHT_BOTTOM:
canvas.drawLine(width, 0, width, height, paint);
canvas.drawLine(0, height, width, height, paint);
break;
}
}
public void setColor(int color){
cornerColor = color;
paint.setColor(cornerColor);
invalidate();
}
public void setLineWidth(int dp){
cornerWidth = dip2px(dp);
paint.setStrokeWidth(cornerWidth);
invalidate();
}
public int dip2px(int dp) {
float density = getContext().getResources().getDisplayMetrics().density;
return (int) (dp * density + 0.5);
}
}
@@ -0,0 +1,61 @@
package cn.bertsir.zbar.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;
import cn.bertsir.zbar.R;
import static android.R.attr.width;
/**
* Created by Bert on 2017/9/22.
*/
@Deprecated
public class LineView extends View {
private Paint paint;//声明画笔
private Canvas canvas;//画布
private int line_color = getResources().getColor(R.color.common_color);
private Shader mShader;
public LineView(Context context) {
super(context);
}
public LineView(Context context, AttributeSet attrs) {
super(context, attrs);
paint=new Paint();//创建一个画笔
canvas=new Canvas();
paint.setStyle(Paint.Style.FILL);//设置非填充
paint.setStrokeWidth(10);//笔宽5像素
// paint.setColor(line_color);//设置为红笔
paint.setAntiAlias(true);//锯齿不显示
}
public void setLinecolor(int color){
line_color = color;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
String line_colors = String.valueOf(Integer.toHexString(line_color));
line_colors = line_colors.substring(line_colors.length() - 6, line_colors.length() - 0);
mShader = new LinearGradient(0,0,getMeasuredWidth(),0,new int[] {Color.parseColor("#00"+line_colors),line_color, Color.parseColor("#00"+line_colors),},null,
Shader.TileMode.CLAMP);
paint.setShader(mShader);
canvas.drawLine(0, 0, width, 0, paint);
}
}
@@ -0,0 +1,285 @@
package cn.bertsir.zbar.view;
import android.animation.ValueAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.DecelerateInterpolator;
import cn.bertsir.zbar.R;
/**
* Created by Bert on 2019-09-16.
* Mail: bertsir@163.com
*/
public class ScanLineView extends View {
private static final String TAG = "ScanView";
public static final int style_gridding = 0;//扫描区域的样式
public static final int style_radar = 1;
public static final int style_hybrid = 2;
public static final int style_line = 3;
private Rect mFrame;//最佳扫描区域的Rect
private Paint mScanPaint_Gridding;//网格样式画笔
private Paint mScanPaint_Radio;//雷达样式画笔
private Paint mScanPaint_Line;//线条样式画笔
private Path mBoundaryLinePath;//边框path
private Path mGriddingPath;//网格样式的path
private LinearGradient mLinearGradient_Radar;//雷达样式的画笔shader
private LinearGradient mLinearGradient_Gridding;//网格画笔的shader
private LinearGradient mLinearGradient_line;
private float mGriddingLineWidth = 4;//网格线的线宽,单位pix
private int mGriddingDensity = 50;//网格样式的,网格密度,值越大越密集
private float mCornerLineLen = 50f;//根据比例计算的边框长度,从四角定点向临近的定点画出的长度
private Matrix mScanMatrix;//变换矩阵,用来实现动画效果
private ValueAnimator mValueAnimator;//值动画,用来变换矩阵操作
private int mScanAnimatorDuration = 1800;//值动画的时长
private int mScancolor;//扫描颜色
private int mScanStyle = style_gridding;//网格 0:网格,1:纵向雷达 2:综合 3:线
private float animatedValue;
public ScanLineView(Context context) {
this(context, null);
}
// This constructor is used when the class is built from an XML resource.
public ScanLineView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScanLineView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// Initialize these once for performance rather than calling them every time in onDraw().
mScanPaint_Gridding = new Paint(Paint.ANTI_ALIAS_FLAG);
mScanPaint_Gridding.setStyle(Paint.Style.STROKE);
mScanPaint_Gridding.setStrokeWidth(mGriddingLineWidth);
mScanPaint_Radio = new Paint(Paint.ANTI_ALIAS_FLAG);
mScanPaint_Radio.setStyle(Paint.Style.FILL);
Resources resources = getResources();
mScancolor = resources.getColor(R.color.common_color);
mScanPaint_Line=new Paint();//创建一个画笔
mScanPaint_Line.setStyle(Paint.Style.FILL);//设置非填充
mScanPaint_Line.setStrokeWidth(10);//笔宽5像素
mScanPaint_Line.setAntiAlias(true);//锯齿不显示
//变换矩阵,用来处理扫描的上下扫描效果
mScanMatrix = new Matrix();
mScanMatrix.setTranslate(0, 30);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mFrame = new Rect(left,top,right,bottom);
initBoundaryAndAnimator();
}
private void initBoundaryAndAnimator() {
if (mBoundaryLinePath == null) {
mBoundaryLinePath = new Path();
mBoundaryLinePath.moveTo(mFrame.left, mFrame.top + mCornerLineLen);
mBoundaryLinePath.lineTo(mFrame.left, mFrame.top);
mBoundaryLinePath.lineTo(mFrame.left + mCornerLineLen, mFrame.top);
mBoundaryLinePath.moveTo(mFrame.right - mCornerLineLen, mFrame.top);
mBoundaryLinePath.lineTo(mFrame.right, mFrame.top);
mBoundaryLinePath.lineTo(mFrame.right, mFrame.top + mCornerLineLen);
mBoundaryLinePath.moveTo(mFrame.right, mFrame.bottom - mCornerLineLen);
mBoundaryLinePath.lineTo(mFrame.right, mFrame.bottom);
mBoundaryLinePath.lineTo(mFrame.right - mCornerLineLen, mFrame.bottom);
mBoundaryLinePath.moveTo(mFrame.left + mCornerLineLen, mFrame.bottom);
mBoundaryLinePath.lineTo(mFrame.left, mFrame.bottom);
mBoundaryLinePath.lineTo(mFrame.left, mFrame.bottom - mCornerLineLen);
}
if (mValueAnimator == null) {
initScanValueAnim(mFrame.height());
}
}
@SuppressLint("DrawAllocation")
@Override
public void onDraw(Canvas canvas) {
if (mFrame == null||mBoundaryLinePath==null) {
return;
}
switch (mScanStyle) {
case style_gridding:
initGriddingPathAndStyle();
canvas.drawPath(mGriddingPath, mScanPaint_Gridding);
break;
case style_radar:
initRadarStyle();
canvas.drawRect(mFrame, mScanPaint_Radio);
break;
case style_line:
initLineStyle();
canvas.drawLine(0,(mFrame.height()- Math.abs(animatedValue)),getMeasuredWidth(),
(mFrame.height()- Math.abs(animatedValue)), mScanPaint_Line);
break;
case style_hybrid:
default:
initGriddingPathAndStyle();
initRadarStyle();
canvas.drawPath(mGriddingPath, mScanPaint_Gridding);
canvas.drawRect(mFrame, mScanPaint_Radio);
break;
}
}
private void initRadarStyle() {
if (mLinearGradient_Radar == null) {
mLinearGradient_Radar = new LinearGradient(0, mFrame.top, 0, mFrame.bottom + 0.01f * mFrame.height(),
new int[]{Color.TRANSPARENT, Color.TRANSPARENT, mScancolor, Color.TRANSPARENT}, new float[]{0, 0.85f, 0.99f, 1f}, LinearGradient.TileMode.CLAMP);
mLinearGradient_Radar.setLocalMatrix(mScanMatrix);
mScanPaint_Radio.setShader(mLinearGradient_Radar);
}
}
private void initLineStyle() {
if (mLinearGradient_line == null) {
String line_colors = String.valueOf(Integer.toHexString(mScancolor));
line_colors = line_colors.substring(line_colors.length() - 6, line_colors.length() - 0);
mLinearGradient_line = new LinearGradient(0,0,getMeasuredWidth(),0,new int[] {Color.parseColor("#00"+line_colors),
mScancolor, Color.parseColor("#00"+line_colors),},null, Shader.TileMode.CLAMP);
mLinearGradient_line.setLocalMatrix(mScanMatrix);
mScanPaint_Line.setShader(mLinearGradient_line);
}
}
private void initGriddingPathAndStyle() {
if (mGriddingPath == null) {
mGriddingPath = new Path();
float wUnit = mFrame.width() / (mGriddingDensity + 0f);
float hUnit = mFrame.height() / (mGriddingDensity + 0f);
for (int i = 0; i <= mGriddingDensity; i++) {
mGriddingPath.moveTo(mFrame.left + i * wUnit, mFrame.top);
mGriddingPath.lineTo(mFrame.left + i * wUnit, mFrame.bottom);
}
for (int i = 0; i <= mGriddingDensity; i++) {
mGriddingPath.moveTo(mFrame.left, mFrame.top + i * hUnit);
mGriddingPath.lineTo(mFrame.right, mFrame.top + i * hUnit);
}
}
if (mLinearGradient_Gridding == null) {
mLinearGradient_Gridding = new LinearGradient(0, mFrame.top, 0, mFrame.bottom + 0.01f * mFrame.height(), new int[]{Color.TRANSPARENT, Color.TRANSPARENT, mScancolor, Color.TRANSPARENT}, new float[]{0, 0.5f, 0.99f, 1f}, LinearGradient.TileMode.CLAMP);
mLinearGradient_Gridding.setLocalMatrix(mScanMatrix);
mScanPaint_Gridding.setShader(mLinearGradient_Gridding);
}
}
public void initScanValueAnim(int height) {
mValueAnimator = new ValueAnimator();
mValueAnimator.setDuration(mScanAnimatorDuration);
mValueAnimator.setFloatValues(-height, 0);
mValueAnimator.setRepeatMode(ValueAnimator.RESTART);
mValueAnimator.setInterpolator(new DecelerateInterpolator());
mValueAnimator.setRepeatCount(Animation.INFINITE);
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if(mLinearGradient_Gridding == null){
initGriddingPathAndStyle();
}
if(mLinearGradient_Radar == null){
initRadarStyle();
}
if(mLinearGradient_line == null){
initLineStyle();
}
if (mScanMatrix != null ) {
animatedValue = (float) animation.getAnimatedValue();
mScanMatrix.setTranslate(0, animatedValue);
mLinearGradient_Gridding.setLocalMatrix(mScanMatrix);
mLinearGradient_Radar.setLocalMatrix(mScanMatrix);
mLinearGradient_line.setLocalMatrix(mScanMatrix);
//mScanPaint.setShader(mLinearGradient); //不是必须的设置到shader即可
invalidate();
}
}
});
mValueAnimator.start();
}
@Override
protected void onDetachedFromWindow() {
if (mValueAnimator != null && mValueAnimator.isRunning()) {
mValueAnimator.cancel();
}
super.onDetachedFromWindow();
}
//设定扫描的颜色
public void setScancolor(int colorValue) {
this.mScancolor = colorValue;
}
public void setScanAnimatorDuration(int duration) {
this.mScanAnimatorDuration = duration;
}
/*
* @description 扫描区域的样式
* @scanStyle
*
* */
public void setScanStyle(int scanStyle) {
this.mScanStyle = scanStyle;
}
/*
* 扫描区域网格的样式
* @params strokeWidth:网格的线宽
* @params density:网格的密度
* */
public void setScanGriddingStyle(float strokeWidh, int density) {
this.mGriddingLineWidth = strokeWidh;
this.mGriddingDensity = density;
}
}
@@ -0,0 +1,134 @@
package cn.bertsir.zbar.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import com.gyf.immersionbar.ImmersionBar;
import java.util.ArrayList;
import cn.bertsir.zbar.Qr.Symbol;
import cn.bertsir.zbar.QrConfig;
import cn.bertsir.zbar.R;
/**
* Created by Bert on 2017/9/20.
*/
public class ScanView extends FrameLayout {
private ScanLineView iv_scan_line;
private FrameLayout fl_scan;
private int CURRENT_TYEP = 1;
private CornerView cnv_left_top;
private CornerView cnv_left_bottom;
private CornerView cnv_right_top;
private CornerView cnv_right_bottom;
private ArrayList<CornerView> cornerViews;
private int line_speed = 3000;
public ScanView(Context context) {
super(context);
initView(context);
}
public ScanView(Context context,AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public ScanView(Context context,AttributeSet attrs,int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context mContext){
View scan_view = View.inflate(mContext, R.layout.view_scan, this);
cnv_left_top = (CornerView) scan_view.findViewById(R.id.cnv_left_top);
cnv_left_bottom = (CornerView) scan_view.findViewById(R.id.cnv_left_bottom);
cnv_right_top = (CornerView) scan_view.findViewById(R.id.cnv_right_top);
cnv_right_bottom = (CornerView) scan_view.findViewById(R.id.cnv_right_bottom);
cornerViews = new ArrayList<>();
cornerViews.add(cnv_left_top);
cornerViews.add(cnv_left_bottom);
cornerViews.add(cnv_right_top);
cornerViews.add(cnv_right_bottom);
iv_scan_line = (ScanLineView) scan_view.findViewById(R.id.iv_scan_line);
fl_scan = (FrameLayout) scan_view.findViewById(R.id.fl_scan);
getViewWidthHeight();
}
/**
* 设置扫描速度
* @param speed
*/
public void setLineSpeed(int speed){
iv_scan_line.setScanAnimatorDuration(speed);
}
/**
* 设置扫描样式
*/
public void setScanLineStyle(int style){
iv_scan_line.setScanStyle(style);
}
public void setType(int type){
CURRENT_TYEP = type;
LinearLayout.LayoutParams fl_params = (LinearLayout.LayoutParams) fl_scan.getLayoutParams();
if(CURRENT_TYEP == QrConfig.SCANVIEW_TYPE_QRCODE){
fl_params.width = dip2px(200);
fl_params.height = dip2px(200);
}else if(CURRENT_TYEP == QrConfig.SCANVIEW_TYPE_BARCODE){
fl_params.width = dip2px(300);
fl_params.height = dip2px(100);
}
fl_scan.setLayoutParams(fl_params);
}
public void setCornerColor(int color){
for (int i = 0; i < cornerViews.size(); i++) {
cornerViews.get(i).setColor(color);
}
}
public void setCornerWidth(int dp){
for (int i = 0; i < cornerViews.size(); i++) {
cornerViews.get(i).setLineWidth(dp);
}
}
public void setLineColor(int color){
iv_scan_line.setScancolor(color);
}
public int dip2px(int dp) {
float density = getContext().getResources().getDisplayMetrics().density;
return (int) (dp * density + 0.5);
}
public void getViewWidthHeight(){
fl_scan.post(new Runnable() {
@Override
public void run() {
Symbol.cropWidth = fl_scan.getWidth();
Symbol.cropHeight = fl_scan.getHeight();
}
});
}
}
@@ -0,0 +1,104 @@
package cn.bertsir.zbar.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.SeekBar;
import cn.bertsir.zbar.R;
/**
* Created by Bert on 2019/3/1.
* Mail: bertsir@163.com
*/
public class VerticalSeekBar extends SeekBar {
private static final String TAG = VerticalSeekBar.class.getSimpleName();
public static final int ROTATION_ANGLE_CW_90 = 90;
public static final int ROTATION_ANGLE_CW_270 = 270;
private int mRotationAngle = ROTATION_ANGLE_CW_90;
public VerticalSeekBar(Context context) {
super(context);//注意是super 而不是调用其他构造函数
initialize(context, null, 0, 0);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
initialize(context, attrs, 0, 0);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize(context, attrs, defStyle, 0);
}
private void initialize(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
if (attrs != null) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.VerticalSeekBar, defStyleAttr, defStyleRes);
final int rotationAngle = a.getInteger(R.styleable.VerticalSeekBar_seekBarRotation, 0);
if (isValidRotationAngle(rotationAngle)) {
mRotationAngle = rotationAngle;
}
a.recycle();
}
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas c) {
if (mRotationAngle == ROTATION_ANGLE_CW_270) {
//从下到上
c.rotate(270);
c.translate(-getHeight(), 0);
} else if (mRotationAngle == ROTATION_ANGLE_CW_90) {
//从上到下
c.rotate(90);
c.translate(0, -getWidth());
}
super.onDraw(c);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
if (mRotationAngle == ROTATION_ANGLE_CW_270) {
//从下到上
setProgress(getMax() - (int) (getMax() * event.getY() / getHeight()));
} else if (mRotationAngle == ROTATION_ANGLE_CW_90) {
//从上到下
setProgress((int) (getMax() * event.getY() / getHeight()));
}
onSizeChanged(getWidth(), getHeight(), 0, 0);
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
private static boolean isValidRotationAngle(int angle) {
return (angle == ROTATION_ANGLE_CW_90 || angle == ROTATION_ANGLE_CW_270);
}
}
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@android:color/white"/>
</selector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 997 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<!-- 填充的颜色 -->
<solid android:color="#c1333333" />
<!-- 设置按钮的四个角为弧形 -->
<!-- android:radius 弧形的半径 -->
<corners android:radius="360dip" />
<!-- padding: Button 里面的文字与Button边界的间隔 -->
<padding
android:left="0dp"
android:top="0dp"
android:right="0dp"
android:bottom="0dp"
/>
</shape>
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#c1333333" />
<corners android:radius="5dip" />
</shape>
@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!-- 二维码识别界面 -->
<cn.bertsir.zbar.CameraPreview
android:id="@+id/cp"
android:layout_width="match_parent"
android:layout_height="match_parent"></cn.bertsir.zbar.CameraPreview>
<cn.bertsir.zbar.view.ScanView
android:id="@+id/sv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<FrameLayout
android:id="@+id/fl_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFEFEFEF"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="bottom"
>
<ImageView
android:id="@+id/mo_scanner_back"
android:layout_width="50dp"
android:layout_height="50dp"
android:padding="10dp"
android:layout_gravity="center_vertical"
android:src="@drawable/top_back" />
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/white"
android:text="扫描二维码"
android:layout_gravity="center"
android:gravity="center"
android:textSize="20sp"
/>
</FrameLayout>
</FrameLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_gravity="center"
android:layout_marginTop="50dp"
>
<TextView
android:id="@+id/tv_des"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center_horizontal"
android:text="扫一扫"
android:textColor="#ffffffff"
android:textSize="15sp" />
</LinearLayout>
<ImageView
android:id="@+id/iv_flash"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/circle_trans_black"
android:src="@drawable/scanner_light"
android:padding="5dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="70dp"
android:layout_marginRight="10dp"
/>
<ImageView
android:id="@+id/iv_album"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/circle_trans_black"
android:src="@drawable/scanner_album"
android:padding="5dp"
android:layout_gravity="bottom|right"
android:layout_marginBottom="20dp"
android:layout_marginRight="10dp"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_gravity="right|center_vertical"
android:layout_marginRight="30dp"
>
<cn.bertsir.zbar.view.VerticalSeekBar
android:id="@+id/vsb_zoom"
android:layout_width="wrap_content"
android:layout_height="200dp"
app:seekBarRotation ="CW270"
/>
</LinearLayout>
</FrameLayout>
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_dialog_bg"
android:orientation="vertical"
android:gravity="center"
>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center"
android:layout_margin="30dp"
>
<ProgressBar
android:id="@+id/pb_loading"
android:layout_width="40dp"
android:layout_height="40dp"
/>
<TextView
android:id="@+id/tv_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textSize="14sp"
android:textColor="#fff"
android:text="请稍后..."
android:layout_marginTop="10dp"
/>
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 扫描动画 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="160dp"
android:src="@drawable/shadow"
android:scaleType="fitXY"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@drawable/shadow"
android:layout_weight="1"
android:scaleType="fitXY"
/>
<FrameLayout
android:id="@+id/fl_scan"
android:layout_width="@dimen/scan_frame_width"
android:layout_height="@dimen/scan_frame_width"
android:layout_gravity="center_horizontal"
android:background="@drawable/capture1"
>
<cn.bertsir.zbar.view.CornerView
android:id="@+id/cnv_left_top"
android:layout_width="20dp"
android:layout_height="20dp"
app:corner_width="5dp"
android:visibility="gone"
app:corner_gravity="leftTop"
/>
<cn.bertsir.zbar.view.CornerView
android:id="@+id/cnv_left_bottom"
android:layout_width="20dp"
android:layout_height="20dp"
app:corner_width="5dp"
android:visibility="gone"
app:corner_gravity="leftBottom"
android:layout_gravity="bottom|left"
/>
<cn.bertsir.zbar.view.CornerView
android:id="@+id/cnv_right_top"
android:layout_width="20dp"
android:layout_height="20dp"
app:corner_width="5dp"
android:visibility="gone"
app:corner_gravity="rightTop"
android:layout_gravity="right|top"
/>
<cn.bertsir.zbar.view.CornerView
android:id="@+id/cnv_right_bottom"
android:layout_width="20dp"
android:layout_height="20dp"
app:corner_width="5dp"
android:visibility="gone"
app:corner_gravity="rightBottom"
android:layout_gravity="right|bottom"
/>
<cn.bertsir.zbar.view.ScanLineView
android:id="@+id/iv_scan_line"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@drawable/shadow"
android:layout_weight="1"
android:scaleType="fitXY"
/>
</LinearLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scaleType="fitXY"
android:src="@drawable/shadow"
/>
</LinearLayout>
</LinearLayout>
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CornerView">
<attr name="corner_color" format="color" />
<attr name="corner_width" format="dimension" />
<attr name="corner_gravity" format="enum">
<enum name="leftBottom" value="1" />
<enum name="rightBottom" value="3" />
<enum name="leftTop" value="0" />
<enum name="rightTop" value="2" />
</attr>
</declare-styleable>
<declare-styleable name="VerticalSeekBar">
<attr name="seekBarRotation">
<enum name="CW90" value="90" />
<enum name="CW270" value="270" />
</attr>
</declare-styleable>
</resources>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="common_color">#ff5f00</color>
</resources>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="scan_frame_width">200dp</dimen>
</resources>
@@ -0,0 +1,3 @@
<resources>
<string name="app_name">zBarLibary</string>
</resources>
+26
View File
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AlertDialogStyle" parent="@android:style/Theme.Dialog">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowFrame">@null</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsTranslucent">true</item>
</style>
<style name="ActivityTranslucent">
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:activityOpenEnterAnimation">@null</item>
<item name="android:activityOpenExitAnimation">@null</item>
<item name="android:activityCloseEnterAnimation">@null</item>
<item name="android:activityCloseExitAnimation">@null</item>
</style>
</resources>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="camera_photos"
path="." />
</paths>