diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 97ee803..774b355 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/README.md b/README.md index 4e07666..401ddbd 100644 --- a/README.md +++ b/README.md @@ -45,17 +45,17 @@ ZXingLite for Android 是ZXing的精简版,基于ZXing库优化扫码和生成 com.king.zxing zxing-lite - 1.1.0 + 1.1.1 pom ``` ### Gradle: ```gradle -implementation 'com.king.zxing:zxing-lite:1.1.0' +implementation 'com.king.zxing:zxing-lite:1.1.1' ``` ### Lvy: ```lvy - + ``` @@ -106,6 +106,13 @@ api 'com.google.zxing:core:3.3.3' CodeUtils.createBarCode(content, BarcodeFormat.CODE_128,800,200); ``` +如果直接使用CaptureActivity需在您项目的AndroidManifest中添加如下配置 +```Xml + +``` + ### 快速实现扫码有以下几种方式: > 1、直接使用CaptureActivity或者CaptureFragment。(纯洁的扫码,无任何添加剂) @@ -121,8 +128,12 @@ api 'com.google.zxing:core:3.3.3' ## 版本记录 +#### v1.1.1:2019-5-20 +* 支持扫二维码过小时,自动缩放 +* 支持垂直条形码识别(增强条形码识别,默认不支持,需CaptureHelper.supportVerticalCode(true)开启) + #### v1.1.0:2019-4-19 -* 将扫码相关逻辑与界面分离,ZXingLite使用更容易扩展。 +* 将扫码相关逻辑与界面分离,ZXingLite使用更容易扩展 * 新增CaptureFragment #### v1.0.7:2019-4-9 diff --git a/app/release/app-release.apk b/app/release/app-release.apk index 0c3126a..12b36ab 100644 Binary files a/app/release/app-release.apk and b/app/release/app-release.apk differ diff --git a/app/release/output.json b/app/release/output.json index 90a54ae..fc5437f 100644 --- a/app/release/output.json +++ b/app/release/output.json @@ -1 +1 @@ -[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":9,"versionName":"1.1.0","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file +[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":10,"versionName":"1.1.1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}] \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 51e3d6f..171b782 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -29,8 +29,7 @@ android:name=".EasyCaptureActivity" android:screenOrientation="portrait"/> + android:name=".CustomCaptureActivity"/> Jenly */ -public class CaptureHandler extends Handler { +public class CaptureHandler extends Handler implements ResultPointCallback { private static final String TAG = CaptureHandler.class.getSimpleName(); @@ -35,6 +34,20 @@ public class CaptureHandler extends Handler { private final CameraManager cameraManager; private final Activity activity; private final ViewfinderView viewfinderView; + /** + * 是否支持垂直的条形码 + */ + private boolean isSupportVerticalCode; + + /** + * 是否返回扫码原图 + */ + private boolean isReturnBitmap; + + /** + * 是否支持自动缩放 + */ + private boolean isSupportAutoZoom; private enum State { @@ -51,8 +64,7 @@ public class CaptureHandler extends Handler { this.activity = activity; this.viewfinderView = viewfinderView; this.onCaptureListener = onCaptureListener; - decodeThread = new DecodeThread(activity,cameraManager,this, decodeFormats, baseHints, characterSet, - new ViewfinderResultPointCallback(viewfinderView)); + decodeThread = new DecodeThread(activity,cameraManager,this, decodeFormats, baseHints, characterSet, this); decodeThread.start(); state = State.SUCCESS; @@ -83,47 +95,11 @@ public class CaptureHandler extends Handler { } onCaptureListener.onHandleDecode((Result) message.obj, barcode, scaleFactor); + } else if (message.what == R.id.decode_failed) {// We're decoding as fast as possible, so when one decode fails, start another. state = State.PREVIEW; cameraManager.requestPreviewFrame(decodeThread.getHandler(), R.id.decode); - } else if (message.what == R.id.return_scan_result) { - activity.setResult(Activity.RESULT_OK, (Intent) message.obj); - activity.finish(); - - } else if (message.what == R.id.launch_product_query) { - String url = (String) message.obj; - - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.addFlags(Intents.FLAG_NEW_DOC); - intent.setData(Uri.parse(url)); - - ResolveInfo resolveInfo = - activity.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY); - String browserPackageName = null; - if (resolveInfo != null && resolveInfo.activityInfo != null) { - browserPackageName = resolveInfo.activityInfo.packageName; - Log.d(TAG, "Using browser in package " + browserPackageName); - } - - // Needed for default Android browser / Chrome only apparently - if (browserPackageName != null) { - switch (browserPackageName) { - case "com.android.browser": - case "com.android.chrome": - intent.setPackage(browserPackageName); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(Browser.EXTRA_APPLICATION_ID, browserPackageName); - break; - } - } - - try { - activity.startActivity(intent); - } catch (ActivityNotFoundException ignored) { - Log.w(TAG, "Can't find anything to handle VIEW of URI " + url); - } - } } @@ -151,4 +127,75 @@ public class CaptureHandler extends Handler { viewfinderView.drawViewfinder(); } } + + @Override + public void foundPossibleResultPoint(ResultPoint point) { + if(viewfinderView!=null){ + ResultPoint resultPoint = transform(point); + viewfinderView.addPossibleResultPoint(resultPoint); + } + } + + private boolean isScreenPortrait(Context context){ + WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + Display display = manager.getDefaultDisplay(); + Point screenResolution = new Point(); + display.getSize(screenResolution); + return screenResolution.x < screenResolution.y; + } + + /** + * + * @return + */ + private ResultPoint transform(ResultPoint originPoint) { + Point screenPoint = cameraManager.getScreenResolution(); + Point cameraPoint = cameraManager.getCameraResolution(); + + float scaleX; + float scaleY; + float x; + float y; + + if(screenPoint.x < screenPoint.y){ + scaleX = 1.0f * screenPoint.x / cameraPoint.y; + scaleY = 1.0f * screenPoint.y / cameraPoint.x; + + x = originPoint.getX() * scaleX - Math.max(screenPoint.x,cameraPoint.y)/2; + y = originPoint.getY() * scaleY - Math.min(screenPoint.y,cameraPoint.x)/2; + }else{ + scaleX = 1.0f * screenPoint.x / cameraPoint.x; + scaleY = 1.0f * screenPoint.y / cameraPoint.y; + + x = originPoint.getX() * scaleX - Math.min(screenPoint.y,cameraPoint.y)/2; + y = originPoint.getY() * scaleY - Math.max(screenPoint.x,cameraPoint.x)/2; + } + + + return new ResultPoint(x,y); + } + + public boolean isSupportVerticalCode() { + return isSupportVerticalCode; + } + + public void setSupportVerticalCode(boolean supportVerticalCode) { + isSupportVerticalCode = supportVerticalCode; + } + + public boolean isReturnBitmap() { + return isReturnBitmap; + } + + public void setReturnBitmap(boolean returnBitmap) { + isReturnBitmap = returnBitmap; + } + + public boolean isSupportAutoZoom() { + return isSupportAutoZoom; + } + + public void setSupportAutoZoom(boolean supportAutoZoom) { + isSupportAutoZoom = supportAutoZoom; + } } diff --git a/lib/src/main/java/com/king/zxing/CaptureHelper.java b/lib/src/main/java/com/king/zxing/CaptureHelper.java index dc63b62..9aa5b5a 100644 --- a/lib/src/main/java/com/king/zxing/CaptureHelper.java +++ b/lib/src/main/java/com/king/zxing/CaptureHelper.java @@ -75,6 +75,12 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture */ private boolean isSupportZoom = true; private float oldDistance; + + /** + * 是否支持自动缩放(变焦),默认支持 + */ + private boolean isSupportAutoZoom = true; + /** * 是否支持连扫,默认不支持 */ @@ -92,6 +98,21 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture */ private boolean isVibrate; + /** + * 是否支持垂直的条形码 + */ + private boolean isSupportVerticalCode; + + /** + * 是否返回扫码原图 + */ + private boolean isReturnBitmap; + + /** + * 是否支持全屏扫码识别 + */ + private boolean isFullScreenScan; + private OnCaptureCallback onCaptureCallback; @@ -115,7 +136,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture ambientLightManager = new AmbientLightManager(activity); cameraManager = new CameraManager(activity); - + cameraManager.setFullScreenScan(isFullScreenScan); callback = new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { @@ -236,6 +257,10 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture return false; } + /** + * 初始化Camera + * @param surfaceHolder + */ private void initCamera(SurfaceHolder surfaceHolder) { if (surfaceHolder == null) { throw new IllegalStateException("No SurfaceHolder provided"); @@ -249,6 +274,9 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture // Creating the handler starts the preview, which can also throw a RuntimeException. if (captureHandler == null) { captureHandler = new CaptureHandler(activity,viewfinderView,onCaptureListener, decodeFormats, decodeHints, characterSet, cameraManager); + captureHandler.setSupportVerticalCode(isSupportVerticalCode); + captureHandler.setReturnBitmap(isReturnBitmap); + captureHandler.setSupportAutoZoom(isSupportAutoZoom); } } catch (IOException ioe) { Log.w(TAG, ioe); @@ -388,10 +416,10 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture public void onResult(Result result){ String text = result.getText(); if(isContinuousScan){ + if(onCaptureCallback!=null){ + onCaptureCallback.onResultCallback(text); + } if(isAutoRestartPreviewAndDecode){ - if(onCaptureCallback!=null){ - onCaptureCallback.onResultCallback(text); - } restartPreviewAndDecode(); } }else{ @@ -461,7 +489,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture } /** - * + * 设置支持的解码一/二维码格式,默认常规的码都支持 * @param decodeFormats * @return */ @@ -471,7 +499,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture } /** - * + * {@link DecodeHintType} * @param decodeHints * @return */ @@ -481,7 +509,7 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture } /** - * + * 设置解码时编码字符集 * @param characterSet * @return */ @@ -490,6 +518,60 @@ public class CaptureHelper implements CaptureLifecycle,CaptureTouchEvent,Capture return this; } + /** + * 设置是否支持扫垂直的条码 + * @param supportVerticalCode 默认为false,想要增强扫条码识别度时可使用,相应的会增加性能消耗。 + * @return + */ + public CaptureHelper supportVerticalCode(boolean supportVerticalCode) { + this.isSupportVerticalCode = supportVerticalCode; + if(captureHandler!=null){ + captureHandler.setSupportVerticalCode(isSupportVerticalCode); + } + return this; + } + + /** + * 设置返回扫码原图 + * @param returnBitmap 默认为false,当返回true表示扫码就结果会返回扫码原图,相应的会增加性能消耗。 + * @return + */ + public CaptureHelper returnBitmap(boolean returnBitmap) { + isReturnBitmap = returnBitmap; + if(captureHandler!=null){ + captureHandler.setReturnBitmap(isReturnBitmap); + } + return this; + } + + + /** + * 设置是否支持自动缩放 + * @param supportAutoZoom + * @return + */ + public CaptureHelper supportAutoZoom(boolean supportAutoZoom) { + isSupportAutoZoom = supportAutoZoom; + if(captureHandler!=null){ + captureHandler.setSupportAutoZoom(isSupportAutoZoom); + } + return this; + } + + /** + * 设置是否支持全屏扫码识别 + * @param fullScreenScan + * @return + */ + public CaptureHelper fullScreenScan(boolean fullScreenScan) { + isFullScreenScan = fullScreenScan; + if(cameraManager!=null){ + cameraManager.setFullScreenScan(isFullScreenScan); + } + return this; + } + + /** * 设置扫码回调 * @param callback diff --git a/lib/src/main/java/com/king/zxing/DecodeHandler.java b/lib/src/main/java/com/king/zxing/DecodeHandler.java index 8a45ca7..ad1acfc 100644 --- a/lib/src/main/java/com/king/zxing/DecodeHandler.java +++ b/lib/src/main/java/com/king/zxing/DecodeHandler.java @@ -18,17 +18,9 @@ package com.king.zxing; import android.content.Context; import android.graphics.Bitmap; -import com.google.zxing.BinaryBitmap; -import com.google.zxing.DecodeHintType; -import com.google.zxing.MultiFormatReader; -import com.google.zxing.NotFoundException; -import com.google.zxing.PlanarYUVLuminanceSource; -import com.google.zxing.Result; -import com.google.zxing.common.GlobalHistogramBinarizer; -import com.google.zxing.common.HybridBinarizer; -import com.king.zxing.camera.CameraManager; - import android.graphics.Point; +import android.graphics.PointF; +import android.hardware.Camera; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -37,6 +29,16 @@ import android.util.Log; import android.view.Display; import android.view.WindowManager; +import com.google.zxing.BarcodeFormat; +import com.google.zxing.BinaryBitmap; +import com.google.zxing.DecodeHintType; +import com.google.zxing.MultiFormatReader; +import com.google.zxing.PlanarYUVLuminanceSource; +import com.google.zxing.Result; +import com.google.zxing.ResultPoint; +import com.google.zxing.common.HybridBinarizer; +import com.king.zxing.camera.CameraManager; + import java.io.ByteArrayOutputStream; import java.util.Map; @@ -46,11 +48,13 @@ final class DecodeHandler extends Handler { private final Context context; private final CameraManager cameraManager; - private final Handler handler; + private final CaptureHandler handler; private final MultiFormatReader multiFormatReader; private boolean running = true; - DecodeHandler(Context context, CameraManager cameraManager,Handler handler, Map hints) { + private long lastZoomTime; + + DecodeHandler(Context context, CameraManager cameraManager,CaptureHandler handler, Map hints) { multiFormatReader = new MultiFormatReader(); multiFormatReader.setHints(hints); this.context = context; @@ -64,7 +68,7 @@ final class DecodeHandler extends Handler { return; } if (message.what == R.id.decode) { - decode((byte[]) message.obj, message.arg1, message.arg2,isScreenPortrait()); + decode((byte[]) message.obj, message.arg1, message.arg2,isScreenPortrait(),handler.isSupportVerticalCode()); } else if (message.what == R.id.quit) { running = false; @@ -89,11 +93,85 @@ final class DecodeHandler extends Handler { * @param width The width of the preview frame. * @param height The height of the preview frame. */ - private void decode(byte[] data, int width, int height,boolean isScreenPortrait) { + private void decode(byte[] data, int width, int height,boolean isScreenPortrait,boolean isSupportVerticalCode) { long start = System.currentTimeMillis(); Result rawResult = null; + PlanarYUVLuminanceSource source = buildPlanarYUVLuminanceSource(data,width,height,isScreenPortrait); + + if (source != null) { + BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); + try { + rawResult = multiFormatReader.decodeWithState(bitmap); + } catch (Exception e) { + if(isSupportVerticalCode){ + source = buildPlanarYUVLuminanceSource(data,width,height,!isScreenPortrait); + if(source!=null){ + BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source)); + try{ + rawResult = multiFormatReader.decodeWithState(bitmap1); + }catch (Exception e1){ + + } + } + + } + + } finally { + multiFormatReader.reset(); + } + } + + if (rawResult != null) { + // Don't log the barcode contents for security. + long end = System.currentTimeMillis(); + Log.d(TAG, "Found barcode in " + (end - start) + " ms"); + + BarcodeFormat barcodeFormat = rawResult.getBarcodeFormat(); + if(handler!=null && handler.isSupportAutoZoom() && barcodeFormat == BarcodeFormat.QR_CODE){ + + ResultPoint[] resultPoints = rawResult.getResultPoints(); + if(resultPoints.length >= 3){ + float distance1 = ResultPoint.distance(resultPoints[0],resultPoints[1]); + float distance2 = ResultPoint.distance(resultPoints[1],resultPoints[2]); + float distance3 = ResultPoint.distance(resultPoints[0],resultPoints[2]); + int maxDistance = (int)Math.max(Math.max(distance1,distance2),distance3); + if(handleAutoZoom(maxDistance,width)){ + Message message = Message.obtain(); + message.what = R.id.decode_succeeded; + message.obj = rawResult; + if(handler.isReturnBitmap()){ + Bundle bundle = new Bundle(); + bundleThumbnail(source, bundle); + message.setData(bundle); + } + handler.sendMessageDelayed(message,300); + return; + } + } + + + } + + if (handler != null) { + Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult); + if(handler.isReturnBitmap()){ + Bundle bundle = new Bundle(); + bundleThumbnail(source, bundle); + message.setData(bundle); + } + message.sendToTarget(); + } + } else { + if (handler != null) { + Message message = Message.obtain(handler, R.id.decode_failed); + message.sendToTarget(); + } + } + } + + private PlanarYUVLuminanceSource buildPlanarYUVLuminanceSource(byte[] data, int width, int height,boolean isRotate){ PlanarYUVLuminanceSource source; - if(isScreenPortrait){ + if(isRotate){ byte[] rotatedData = new byte[data.length]; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) @@ -106,39 +184,7 @@ final class DecodeHandler extends Handler { }else{ source = cameraManager.buildLuminanceSource(data, width, height); } - if (source != null) { - BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source)); - try { - rawResult = multiFormatReader.decodeWithState(bitmap); - } catch (Exception e) { - BinaryBitmap bitmap1 = new BinaryBitmap(new GlobalHistogramBinarizer(source)); - try { - rawResult = multiFormatReader.decode(bitmap1); - } catch (NotFoundException ne) { - - } - } finally { - multiFormatReader.reset(); - } - } - - if (rawResult != null) { - // Don't log the barcode contents for security. - long end = System.currentTimeMillis(); - Log.d(TAG, "Found barcode in " + (end - start) + " ms"); - if (handler != null) { - Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult); - Bundle bundle = new Bundle(); - bundleThumbnail(source, bundle); - message.setData(bundle); - message.sendToTarget(); - } - } else { - if (handler != null) { - Message message = Message.obtain(handler, R.id.decode_failed); - message.sendToTarget(); - } - } + return source; } private static void bundleThumbnail(PlanarYUVLuminanceSource source, Bundle bundle) { @@ -152,4 +198,31 @@ final class DecodeHandler extends Handler { bundle.putFloat(DecodeThread.BARCODE_SCALED_FACTOR, (float) width / source.getWidth()); } + private boolean handleAutoZoom(int length,int width){ + if(lastZoomTime > System.currentTimeMillis() - 1000){ + return true; + } + + if(lengthSplit a query string into a list of name-value pairs.

- * - *

This is an alternative to the {@link Uri#getQueryParameterNames()} and - * {@link Uri#getQueryParameters(String)}, which are quirky and not suitable - * for exist-only Uri parameters.

- * - *

This method ignores multiple parameters with the same name and returns the - * first one only. This is technically incorrect, but should be acceptable due - * to the method of processing Hints: no multiple values for a hint.

- * - * @param query query to split - * @return name-value pairs - */ - private static Map splitQuery(String query) { - Map map = new HashMap<>(); - int pos = 0; - while (pos < query.length()) { - if (query.charAt(pos) == '&') { - // Skip consecutive ampersand separators. - pos ++; - continue; - } - int amp = query.indexOf('&', pos); - int equ = query.indexOf('=', pos); - if (amp < 0) { - // This is the last element in the query, no more ampersand elements. - String name; - String text; - if (equ < 0) { - // No equal sign - name = query.substring(pos); - name = name.replace('+', ' '); // Preemptively decode + - name = Uri.decode(name); - text = ""; - } else { - // Split name and text. - name = query.substring(pos, equ); - name = name.replace('+', ' '); // Preemptively decode + - name = Uri.decode(name); - text = query.substring(equ + 1); - text = text.replace('+', ' '); // Preemptively decode + - text = Uri.decode(text); - } - if (!map.containsKey(name)) { - map.put(name, text); - } - break; - } - if (equ < 0 || equ > amp) { - // No equal sign until the &: this is a simple parameter with no value. - String name = query.substring(pos, amp); - name = name.replace('+', ' '); // Preemptively decode + - name = Uri.decode(name); - if (!map.containsKey(name)) { - map.put(name, ""); - } - pos = amp + 1; - continue; - } - String name = query.substring(pos, equ); - name = name.replace('+', ' '); // Preemptively decode + - name = Uri.decode(name); - String text = query.substring(equ + 1, amp); - text = text.replace('+', ' '); // Preemptively decode + - text = Uri.decode(text); - if (!map.containsKey(name)) { - map.put(name, text); - } - pos = amp + 1; - } - return map; - } - - static Map parseDecodeHints(Uri inputUri) { - String query = inputUri.getEncodedQuery(); - if (query == null || query.isEmpty()) { - return null; - } - - // Extract parameters - Map parameters = splitQuery(query); - - Map hints = new EnumMap<>(DecodeHintType.class); - - for (DecodeHintType hintType: DecodeHintType.values()) { - - if (hintType == DecodeHintType.CHARACTER_SET || - hintType == DecodeHintType.NEED_RESULT_POINT_CALLBACK || - hintType == DecodeHintType.POSSIBLE_FORMATS) { - continue; // This hint is specified in another way - } - - String parameterName = hintType.name(); - String parameterText = parameters.get(parameterName); - if (parameterText == null) { - continue; - } - if (hintType.getValueType().equals(Object.class)) { - // This is an unspecified type of hint content. Use the value as is. - // TODO: Can we make a different assumption on this? - hints.put(hintType, parameterText); - continue; - } - if (hintType.getValueType().equals(Void.class)) { - // Void hints are just flags: use the constant specified by DecodeHintType - hints.put(hintType, Boolean.TRUE); - continue; - } - if (hintType.getValueType().equals(String.class)) { - // A string hint: use the decoded value. - hints.put(hintType, parameterText); - continue; - } - if (hintType.getValueType().equals(Boolean.class)) { - // A boolean hint: a few values for false, everything else is true. - // An empty parameter is simply a flag-style parameter, assuming true - if (parameterText.isEmpty()) { - hints.put(hintType, Boolean.TRUE); - } else if ("0".equals(parameterText) || - "false".equalsIgnoreCase(parameterText) || - "no".equalsIgnoreCase(parameterText)) { - hints.put(hintType, Boolean.FALSE); - } else { - hints.put(hintType, Boolean.TRUE); - } - - continue; - } - if (hintType.getValueType().equals(int[].class)) { - // An integer array. Used to specify valid lengths. - // Strip a trailing comma as in Java style array initialisers. - if (!parameterText.isEmpty() && parameterText.charAt(parameterText.length() - 1) == ',') { - parameterText = parameterText.substring(0, parameterText.length() - 1); - } - String[] values = COMMA.split(parameterText); - int[] array = new int[values.length]; - for (int i = 0; i < values.length; i++) { - try { - array[i] = Integer.parseInt(values[i]); - } catch (NumberFormatException ignored) { - Log.w(TAG, "Skipping array of integers hint " + hintType + " due to invalid numeric value: '" + values[i] + '\''); - array = null; - break; - } - } - if (array != null) { - hints.put(hintType, array); - } - continue; - } - Log.w(TAG, "Unsupported hint type '" + hintType + "' of type " + hintType.getValueType()); - } - - Log.i(TAG, "Hints from the URI: " + hints); - return hints; - } - - static Map parseDecodeHints(Intent intent) { - Bundle extras = intent.getExtras(); - if (extras == null || extras.isEmpty()) { - return null; - } - Map hints = new EnumMap<>(DecodeHintType.class); - - for (DecodeHintType hintType: DecodeHintType.values()) { - - if (hintType == DecodeHintType.CHARACTER_SET || - hintType == DecodeHintType.NEED_RESULT_POINT_CALLBACK || - hintType == DecodeHintType.POSSIBLE_FORMATS) { - continue; // This hint is specified in another way - } - - String hintName = hintType.name(); - if (extras.containsKey(hintName)) { - if (hintType.getValueType().equals(Void.class)) { - // Void hints are just flags: use the constant specified by the DecodeHintType - hints.put(hintType, Boolean.TRUE); - } else { - Object hintData = extras.get(hintName); - if (hintType.getValueType().isInstance(hintData)) { - hints.put(hintType, hintData); - } else { - Log.w(TAG, "Ignoring hint " + hintType + " because it is not assignable from " + hintData); - } - } - } - } - - Log.i(TAG, "Hints from the Intent: " + hints); - return hints; - } - -} \ No newline at end of file diff --git a/lib/src/main/java/com/king/zxing/ViewfinderResultPointCallback.java b/lib/src/main/java/com/king/zxing/ViewfinderResultPointCallback.java deleted file mode 100644 index 5f475cf..0000000 --- a/lib/src/main/java/com/king/zxing/ViewfinderResultPointCallback.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.king.zxing; - -/* - * Copyright (C) 2009 ZXing authors - * - * 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. - */ - - -import com.google.zxing.ResultPoint; -import com.google.zxing.ResultPointCallback; - -final class ViewfinderResultPointCallback implements ResultPointCallback { - - private final ViewfinderView viewfinderView; - - ViewfinderResultPointCallback(ViewfinderView viewfinderView) { - this.viewfinderView = viewfinderView; - } - - @Override - public void foundPossibleResultPoint(ResultPoint point) { - viewfinderView.addPossibleResultPoint(point); - } - -} \ No newline at end of file diff --git a/lib/src/main/java/com/king/zxing/ViewfinderView.java b/lib/src/main/java/com/king/zxing/ViewfinderView.java index 71d35a4..c8693bf 100644 --- a/lib/src/main/java/com/king/zxing/ViewfinderView.java +++ b/lib/src/main/java/com/king/zxing/ViewfinderView.java @@ -27,9 +27,11 @@ import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; +import android.support.annotation.ColorInt; import android.support.annotation.ColorRes; import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; @@ -39,6 +41,7 @@ import android.text.TextPaint; import android.text.TextUtils; import android.util.AttributeSet; import android.util.DisplayMetrics; +import android.util.Log; import android.util.TypedValue; import android.view.View; @@ -58,7 +61,7 @@ public final class ViewfinderView extends View { private static final long ANIMATION_DELAY = 15L; private static final int CURRENT_POINT_OPACITY = 0xA0; private static final int MAX_RESULT_POINTS = 20; - private static final int POINT_SIZE = 8; + private static final int POINT_SIZE = 20; private static final int CORNER_RECT_WIDTH = 8; //扫描区边角的宽 private static final int CORNER_RECT_HEIGHT = 40; //扫描区边角的高 @@ -67,7 +70,6 @@ public final class ViewfinderView extends View { private Paint paint; private TextPaint textPaint; - private Bitmap resultBitmap; private int maskColor; //扫描区域边框颜色 private int frameColor; @@ -217,7 +219,7 @@ public final class ViewfinderView extends View { this.labelText = labelText; } - public void setLabelTextColor(int color) { + public void setLabelTextColor(@ColorInt int color) { this.labelTextColor = color; } @@ -256,31 +258,23 @@ public final class ViewfinderView extends View { // Draw the exterior (i.e. outside the framing rect) darkened drawExterior(canvas,frame,width,height); - - if (resultBitmap != null) { - // Draw the opaque result bitmap over the scanning rectangle - paint.setAlpha(CURRENT_POINT_OPACITY); - canvas.drawBitmap(resultBitmap, null, frame, paint); - } else { - - // Draw a red "laser scanner" line through the middle to show decoding is active - drawLaserScanner(canvas,frame); - // Draw a two pixel solid black border inside the framing rect - drawFrame(canvas, frame); - // 绘制边角 - drawCorner(canvas, frame); - //绘制提示信息 - drawTextInfo(canvas, frame); - //绘制扫码结果点 - drawResultPoint(canvas,frame); - // Request another update at the animation interval, but only repaint the laser line, - // not the entire viewfinder mask. - postInvalidateDelayed(ANIMATION_DELAY, - frame.left - POINT_SIZE, - frame.top - POINT_SIZE, - frame.right + POINT_SIZE, - frame.bottom + POINT_SIZE); - } + // Draw a red "laser scanner" line through the middle to show decoding is active + drawLaserScanner(canvas,frame); + // Draw a two pixel solid black border inside the framing rect + drawFrame(canvas, frame); + // 绘制边角 + drawCorner(canvas, frame); + //绘制提示信息 + drawTextInfo(canvas, frame); + //绘制扫码结果点 + drawResultPoint(canvas,frame); + // Request another update at the animation interval, but only repaint the laser line, + // not the entire viewfinder mask. + postInvalidateDelayed(ANIMATION_DELAY, + frame.left - POINT_SIZE, + frame.top - POINT_SIZE, + frame.right + POINT_SIZE, + frame.bottom + POINT_SIZE); } /** @@ -469,12 +463,9 @@ public final class ViewfinderView extends View { paint.setAlpha(CURRENT_POINT_OPACITY); paint.setColor(resultPointColor); synchronized (currentPossible) { + float radius = POINT_SIZE / 2.0f; for (ResultPoint point : currentPossible) { - if(point.getX()frame.right || - point.getY()frame.bottom){ - continue; - } - canvas.drawCircle( point.getX(),point.getY(), POINT_SIZE, paint); + canvas.drawCircle( point.getX(),point.getY(), radius, paint); } } } @@ -484,10 +475,6 @@ public final class ViewfinderView extends View { synchronized (currentLast) { float radius = POINT_SIZE / 2.0f; for (ResultPoint point : currentLast) { - if(point.getX()frame.right || - point.getY()frame.bottom){ - continue; - } canvas.drawCircle( point.getX(),point.getY(), radius, paint); } } @@ -495,11 +482,6 @@ public final class ViewfinderView extends View { } public void drawViewfinder() { - Bitmap resultBitmap = this.resultBitmap; - this.resultBitmap = null; - if (resultBitmap != null) { - resultBitmap.recycle(); - } invalidate(); } @@ -519,15 +501,6 @@ public final class ViewfinderView extends View { isShowResultPoint = showResultPoint; } -// /** -// * Draw a bitmap with the result points highlighted instead of the live scanning display. -// * -// * @param barcode An image of the decoded barcode. -// */ -// public void drawResultBitmap(Bitmap barcode) { -// resultBitmap = barcode; -// invalidate(); -// } public void addPossibleResultPoint(ResultPoint point) { if(isShowResultPoint){ @@ -544,4 +517,6 @@ public final class ViewfinderView extends View { } + + } \ No newline at end of file diff --git a/lib/src/main/java/com/king/zxing/camera/CameraManager.java b/lib/src/main/java/com/king/zxing/camera/CameraManager.java index 2221b4f..4319b79 100644 --- a/lib/src/main/java/com/king/zxing/camera/CameraManager.java +++ b/lib/src/main/java/com/king/zxing/camera/CameraManager.java @@ -21,6 +21,7 @@ import android.content.Context; import android.graphics.Point; import android.graphics.Rect; import android.hardware.Camera; +import android.media.FaceDetector; import android.os.Handler; import android.util.Log; import android.view.SurfaceHolder; @@ -58,6 +59,7 @@ public final class CameraManager { private int requestedCameraId = OpenCameraInterface.NO_REQUESTED_CAMERA; private int requestedFramingRectWidth; private int requestedFramingRectHeight; + private boolean isFullScreenScan; /** * Preview frames are delivered here, which we pass on to the registered handler. Make sure to @@ -221,35 +223,29 @@ public final class CameraManager { if (camera == null) { return null; } - Point screenResolution = configManager.getScreenResolution(); - if (screenResolution == null) { + Point point = configManager.getCameraResolution(); + if (point == null) { // Called early, before init even finished return null; } - int width = findDesiredDimensionInRange(screenResolution.x, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH); - int height = findDesiredDimensionInRange(screenResolution.y, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT); + int width = point.x; + int height = point.y; - int size = Math.min(width,height); + if(isFullScreenScan){ + framingRect = new Rect(0,0,width,height); + }else{ + int size = Math.min(width,height); + + int leftOffset = (width - size) / 2; + int topOffset = (height - size) / 2; + framingRect = new Rect(leftOffset, topOffset, leftOffset + size, topOffset + size); + } - int leftOffset = (screenResolution.x - size) / 2; - int topOffset = (screenResolution.y - size) / 2; - framingRect = new Rect(leftOffset, topOffset, leftOffset + size, topOffset + size); - Log.d(TAG, "Calculated framing rect: " + framingRect); } return framingRect; } - private static int findDesiredDimensionInRange(int resolution, int hardMin, int hardMax) { - int dim = 5 * resolution / 8; // Target 5/8 of each dimension - if (dim < hardMin) { - return hardMin; - } - if (dim > hardMax) { - return hardMax; - } - return dim; - } /** * Like {@link #getFramingRect} but coordinates are in terms of the preview frame, @@ -270,6 +266,7 @@ public final class CameraManager { // Called early, before init even finished return null; } + // rect.left = rect.left * cameraResolution.x / screenResolution.x; // rect.right = rect.right * cameraResolution.x / screenResolution.x; // rect.top = rect.top * cameraResolution.y / screenResolution.y; @@ -280,11 +277,28 @@ public final class CameraManager { rect.top = rect.top * cameraResolution.x / screenResolution.y; rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y; + framingRectInPreview = rect; } + return framingRectInPreview; } + public boolean isFullScreenScan() { + return isFullScreenScan; + } + + public void setFullScreenScan(boolean fullScreenScan) { + isFullScreenScan = fullScreenScan; + } + + public Point getCameraResolution() { + return configManager.getCameraResolution(); + } + + public Point getScreenResolution() { + return configManager.getScreenResolution(); + } /** * Allows third party apps to specify the camera ID, rather than determine @@ -337,12 +351,16 @@ public final class CameraManager { if (rect == null) { return null; } + + if(isFullScreenScan){ + return new PlanarYUVLuminanceSource(data,width,height,0,0,width,height,false); + } int size = Math.min(width,height); int left = (width-size)/2; int top = (height-size)/2; // Go ahead and assume it's YUV rather than die. return new PlanarYUVLuminanceSource(data, width, height, left, top, - left + size, top + size, false); + size, size, false); } } \ No newline at end of file diff --git a/versions.gradle b/versions.gradle index 43184be..6fd6860 100644 --- a/versions.gradle +++ b/versions.gradle @@ -1,7 +1,7 @@ //App def app_version = [:] -app_version.versionCode = 9 -app_version.versionName = "1.1.0" +app_version.versionCode = 10 +app_version.versionName = "1.1.1" ext.app_version = app_version //build version