From 1b325e64344bedc8085309e18d1a7407d69277e7 Mon Sep 17 00:00:00 2001 From: Benjamin Cousin Date: Thu, 23 Mar 2017 18:06:51 +0100 Subject: [PATCH] feat(maxTries): add option to try to detect card rectangle and have image in result --- .../io/card/development/SampleActivity.java | 1 + .../java/io/card/payment/CardIOActivity.java | 67 +++++++++++++------ .../java/io/card/payment/CardScanner.java | 10 ++- 3 files changed, 55 insertions(+), 23 deletions(-) diff --git a/SampleApp/src/main/java/io/card/development/SampleActivity.java b/SampleApp/src/main/java/io/card/development/SampleActivity.java index ac3a5120..27dee16b 100644 --- a/SampleApp/src/main/java/io/card/development/SampleActivity.java +++ b/SampleApp/src/main/java/io/card/development/SampleActivity.java @@ -119,6 +119,7 @@ public void onScan(View pressed) { .putExtra(CardIOActivity.EXTRA_GUIDE_COLOR, Color.GREEN) .putExtra(CardIOActivity.EXTRA_SUPPRESS_CONFIRMATION, mSuppressConfirmationToggle.isChecked()) .putExtra(CardIOActivity.EXTRA_SUPPRESS_SCAN, mSuppressScanToggle.isChecked()) + .putExtra(CardIOActivity.EXTRA_MAX_TRY, 5) .putExtra(CardIOActivity.EXTRA_RETURN_CARD_IMAGE, true); try { diff --git a/card.io/src/main/java/io/card/payment/CardIOActivity.java b/card.io/src/main/java/io/card/payment/CardIOActivity.java index 2fe824be..b3cb0126 100644 --- a/card.io/src/main/java/io/card/payment/CardIOActivity.java +++ b/card.io/src/main/java/io/card/payment/CardIOActivity.java @@ -226,6 +226,12 @@ public final class CardIOActivity extends Activity { */ static final String PRIVATE_EXTRA_CAMERA_BYPASS_TEST_MODE = "io.card.payment.cameraBypassTestMode"; + /** + * Int extra. Max number of try (card detected but not the numbers) + */ + public static final String EXTRA_MAX_TRY = "io.card.payment.maxTry"; + + private static int lastResult = 0xca8d10; // arbitrary. chosen to be well above // Activity.RESULT_FIRST_USER. /** @@ -258,6 +264,11 @@ public final class CardIOActivity extends Activity { */ public static final int RESULT_CONFIRMATION_SUPPRESSED = lastResult++; + /** + * result code indicating that only sample was found. + */ + public static final int RESULT_SAMPLE_ONLY = lastResult++; + private static final String TAG = CardIOActivity.class.getSimpleName(); private static final int DEGREE_DELTA = 15; @@ -275,7 +286,7 @@ public final class CardIOActivity extends Activity { private static final float UIBAR_VERTICAL_MARGIN_DP = 15.0f; - private static final long[] VIBRATE_PATTERN = { 0, 70, 10, 40 }; + private static final long[] VIBRATE_PATTERN = {0, 70, 10, 40}; private static final int TOAST_OFFSET_Y = -75; @@ -371,13 +382,13 @@ protected void onCreate(Bundle savedInstanceState) { if (clientData.getBooleanExtra(EXTRA_NO_CAMERA, false)) { Log.i(Util.PUBLIC_LOG_TAG, "EXTRA_NO_CAMERA set to true. Skipping camera."); manualEntryFallbackOrForced = true; - } else if (!CardScanner.processorSupported()){ + } else if (!CardScanner.processorSupported()) { Log.i(Util.PUBLIC_LOG_TAG, "Processor not Supported. Skipping camera."); manualEntryFallbackOrForced = true; } else { try { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { - if(!waitingForPermission) { + if (!waitingForPermission) { if (checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_DENIED) { @@ -478,8 +489,8 @@ private void showCameraScannerOverlay() { Class testScannerClass = Class.forName("io.card.payment.CardScannerTester"); Constructor cons = testScannerClass.getConstructor(this.getClass(), Integer.TYPE); - mCardScanner = (CardScanner) cons.newInstance(new Object[] { this, - mFrameOrientation }); + mCardScanner = (CardScanner) cons.newInstance(new Object[]{this, + mFrameOrientation}); } else { mCardScanner = new CardScanner(this, mFrameOrientation); } @@ -561,7 +572,7 @@ private void doOrientationChange(int orientation) { protected void onResume() { super.onResume(); - if(!waitingForPermission) { + if (!waitingForPermission) { if (manualEntryFallbackOrForced) { nextActivity(); return; @@ -768,6 +779,32 @@ void onEdgeUpdate(DetectionInfo dInfo) { mOverlay.setDetectionInfo(dInfo); } + public void onSampleDetected(Bitmap detectedBitmap) { + mCardScanner.pauseScanning(); + + updateOverlay(detectedBitmap); + Intent dataIntent = new Intent(); + Util.writeCapturedCardImageIfNecessary(getIntent(), dataIntent, mOverlay); + setResultAndFinish(RESULT_SAMPLE_ONLY, dataIntent); + } + + private void updateOverlay(Bitmap detectedBitmap) { + float sf; + if (mFrameOrientation == ORIENTATION_PORTRAIT + || mFrameOrientation == ORIENTATION_PORTRAIT_UPSIDE_DOWN) { + sf = mGuideFrame.right / (float) CardScanner.CREDIT_CARD_TARGET_WIDTH * .95f; + } else { + sf = mGuideFrame.right / (float) CardScanner.CREDIT_CARD_TARGET_WIDTH * 1.15f; + } + + Matrix m = new Matrix(); + m.postScale(sf, sf); + + Bitmap scaledCard = Bitmap.createBitmap(detectedBitmap, 0, 0, detectedBitmap.getWidth(), + detectedBitmap.getHeight(), m, false); + mOverlay.setBitmap(scaledCard); + } + void onCardDetected(Bitmap detectedBitmap, DetectionInfo dInfo) { try { Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); @@ -786,21 +823,7 @@ void onCardDetected(Bitmap detectedBitmap, DetectionInfo dInfo) { mDetectedCard = dInfo.creditCard(); mOverlay.setDetectedCard(mDetectedCard); } - - float sf; - if (mFrameOrientation == ORIENTATION_PORTRAIT - || mFrameOrientation == ORIENTATION_PORTRAIT_UPSIDE_DOWN) { - sf = mGuideFrame.right / (float)CardScanner.CREDIT_CARD_TARGET_WIDTH * .95f; - } else { - sf = mGuideFrame.right / (float)CardScanner.CREDIT_CARD_TARGET_WIDTH * 1.15f; - } - - Matrix m = new Matrix(); - m.postScale(sf, sf); - - Bitmap scaledCard = Bitmap.createBitmap(detectedBitmap, 0, 0, detectedBitmap.getWidth(), - detectedBitmap.getHeight(), m, false); - mOverlay.setBitmap(scaledCard); + updateOverlay(detectedBitmap); if (mDetectOnly) { Intent dataIntent = new Intent(); @@ -1004,7 +1027,7 @@ public void onClick(View v) { }); mUIBar.addView(keyboardBtn); ViewUtil.styleAsButton(keyboardBtn, false, this, useApplicationTheme); - if(!useApplicationTheme){ + if (!useApplicationTheme) { keyboardBtn.setTextSize(Appearance.TEXT_SIZE_SMALL_BUTTON); } keyboardBtn.setMinimumHeight(ViewUtil.typedDimensionValueToPixelsInt( diff --git a/card.io/src/main/java/io/card/payment/CardScanner.java b/card.io/src/main/java/io/card/payment/CardScanner.java index 17020171..37bd4341 100644 --- a/card.io/src/main/java/io/card/payment/CardScanner.java +++ b/card.io/src/main/java/io/card/payment/CardScanner.java @@ -86,6 +86,7 @@ private native void nScanFrame(byte[] data, int frameWidth, int frameHeight, int // member data protected WeakReference mScanActivityRef; private boolean mSuppressScan = false; + private int mMaxTry = 0; private boolean mScanExpiry; private int mUnblurDigits = DEFAULT_UNBLUR_DIGITS; @@ -112,6 +113,8 @@ private native void nScanFrame(byte[] data, int frameWidth, int frameHeight, int private int numAutoRefocus; private int numManualTorchChange; private int numFramesSkipped; + private int numTry = 0; + // ------------------------------------------------------------------------ // STATIC INITIALIZATION @@ -157,7 +160,7 @@ private native void nScanFrame(byte[] data, int frameWidth, int frameHeight, int /** * Custom loadLibrary method that first tries to load the libraries from the built-in libs * directory and if it fails, tries to use the alternative libs path if one is set. - * + *

* No checks are performed to ensure that the native libraries match the cardIO library version. * This needs to be handled by the consuming application. */ @@ -193,6 +196,7 @@ static boolean processorSupported() { Intent scanIntent = scanActivity.getIntent(); if (scanIntent != null) { mSuppressScan = scanIntent.getBooleanExtra(CardIOActivity.EXTRA_SUPPRESS_SCAN, false); + mMaxTry = scanIntent.getIntExtra(CardIOActivity.EXTRA_MAX_TRY, 0); mScanExpiry = scanIntent.getBooleanExtra(CardIOActivity.EXTRA_REQUIRE_EXPIRY, false) && scanIntent.getBooleanExtra(CardIOActivity.EXTRA_SCAN_EXPIRY, true); mUnblurDigits = scanIntent.getIntExtra(CardIOActivity.EXTRA_UNBLUR_DIGITS, DEFAULT_UNBLUR_DIGITS); @@ -470,6 +474,10 @@ public void onPreviewFrame(byte[] data, Camera camera) { triggerAutoFocus(false); } else if (dInfo.predicted() || (mSuppressScan && dInfo.detected())) { mScanActivityRef.get().onCardDetected(detectedBitmap, dInfo); + } else if (mMaxTry > 0 && dInfo.detected()) { + if (numTry++ > mMaxTry) { + mScanActivityRef.get().onSampleDetected(detectedBitmap); + } } // give the image buffer back to the camera, AFTER we're done reading // the image.