diff --git a/SampleApp/src/main/java/io/card/development/SampleActivity.java b/SampleApp/src/main/java/io/card/development/SampleActivity.java index ac3a5120..7a0e0291 100644 --- a/SampleApp/src/main/java/io/card/development/SampleActivity.java +++ b/SampleApp/src/main/java/io/card/development/SampleActivity.java @@ -56,6 +56,7 @@ public class SampleActivity extends Activity { private CheckBox mUseCardIOLogoToggle; private CheckBox mShowPayPalActionBarIconToggle; private CheckBox mKeepApplicationThemeToggle; + private CheckBox mFontCameraToggle; private Spinner mLanguageSpinner; private EditText mUnblurEdit; @@ -79,6 +80,8 @@ public void onCreate(Bundle savedInstanceState) { mShowPayPalActionBarIconToggle = (CheckBox) findViewById(R.id.show_paypal_action_bar_icon); mKeepApplicationThemeToggle = (CheckBox) findViewById(R.id.keep_application_theme); + mFontCameraToggle = (CheckBox) findViewById(R.id.front_camera); + mLanguageSpinner = (Spinner) findViewById(R.id.language); mUnblurEdit = (EditText) findViewById(R.id.unblur); @@ -116,6 +119,7 @@ public void onScan(View pressed) { .putExtra(CardIOActivity.EXTRA_LANGUAGE_OR_LOCALE, (String) mLanguageSpinner.getSelectedItem()) .putExtra(CardIOActivity.EXTRA_USE_PAYPAL_ACTIONBAR_ICON, mShowPayPalActionBarIconToggle.isChecked()) .putExtra(CardIOActivity.EXTRA_KEEP_APPLICATION_THEME, mKeepApplicationThemeToggle.isChecked()) + .putExtra(CardIOActivity.EXTRA_FRONT_CAMERA, mFontCameraToggle.isChecked()) .putExtra(CardIOActivity.EXTRA_GUIDE_COLOR, Color.GREEN) .putExtra(CardIOActivity.EXTRA_SUPPRESS_CONFIRMATION, mSuppressConfirmationToggle.isChecked()) .putExtra(CardIOActivity.EXTRA_SUPPRESS_SCAN, mSuppressScanToggle.isChecked()) diff --git a/SampleApp/src/main/res/layout/sample_activity.xml b/SampleApp/src/main/res/layout/sample_activity.xml index 5444e783..1f1f3f5a 100644 --- a/SampleApp/src/main/res/layout/sample_activity.xml +++ b/SampleApp/src/main/res/layout/sample_activity.xml @@ -110,6 +110,12 @@ android:layout_height="wrap_content" android:text="Keep application theme"/> + + true, the front camera will be opened. + * If this value is false (default), the back camera will be opened. + */ + public static final String EXTRA_FRONT_CAMERA = "io.card.payment.frontCamera"; + /** * Boolean extra. Used for testing only. 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..5ee1854d 100644 --- a/card.io/src/main/java/io/card/payment/CardScanner.java +++ b/card.io/src/main/java/io/card/payment/CardScanner.java @@ -113,6 +113,8 @@ private native void nScanFrame(byte[] data, int frameWidth, int frameHeight, int private int numManualTorchChange; private int numFramesSkipped; + private boolean mFrontCamera = false; + // ------------------------------------------------------------------------ // STATIC INITIALIZATION // ------------------------------------------------------------------------ @@ -196,6 +198,7 @@ static boolean processorSupported() { 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); + mFrontCamera = scanIntent.getBooleanExtra(CardIOActivity.EXTRA_FRONT_CAMERA, false); } mScanActivityRef = new WeakReference<>(scanActivity); mFrameOrientation = currentFrameOrientation; @@ -211,9 +214,11 @@ private Camera connectToCamera(int checkInterval, int maxTimeout) { if (useCamera) { do { try { - // Camera.open() will open the back-facing camera. Front cameras are not - // attempted. - return Camera.open(); + if (mFrontCamera) { + return Util.openFrontCamera(); + } else { + return Util.openBackCamera(); + } } catch (RuntimeException e) { try { Log.w(Util.PUBLIC_LOG_TAG, diff --git a/card.io/src/main/java/io/card/payment/Util.java b/card.io/src/main/java/io/card/payment/Util.java index 901cfab4..dd11d319 100644 --- a/card.io/src/main/java/io/card/payment/Util.java +++ b/card.io/src/main/java/io/card/payment/Util.java @@ -80,7 +80,8 @@ private static boolean hardwareSupportCheck() { // Camera needs to open Camera c = null; try { - c = Camera.open(); + // For checking the hardware, we open the default camera: the back one. + c = openBackCamera(); } catch (RuntimeException e) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return true; @@ -113,6 +114,38 @@ private static boolean hardwareSupportCheck() { return true; } + /** + * Open the back camera + * @return the back camera opened + */ + static Camera openBackCamera() { + return Camera.open(); + } + + /** + * Open the front camera + * Inspired from https://stackoverflow.com/questions/2779002/how-do-i-open-the-front-camera-on-the-android-platform + * @return the front camera opened + */ + static Camera openFrontCamera() { + int cameraCount = 0; + Camera cam = null; + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + cameraCount = Camera.getNumberOfCameras(); + for (int camIdx = 0; camIdx < cameraCount; camIdx++) { + Camera.getCameraInfo(camIdx, cameraInfo); + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + try { + cam = Camera.open(camIdx); + } catch (RuntimeException e) { + Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage()); + } + } + } + + return cam; + } + public static String getNativeMemoryStats() { return "(free/alloc'd/total)" + Debug.getNativeHeapFreeSize() + "/" + Debug.getNativeHeapAllocatedSize() + "/" + Debug.getNativeHeapSize();