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();