v416
@@ -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>
|
||||
|
After Width: | Height: | Size: 997 B |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||