diff --git a/hooks/before_build/generateActivity.js b/hooks/before_build/generateActivity.js index d43d251..87b40e5 100644 --- a/hooks/before_build/generateActivity.js +++ b/hooks/before_build/generateActivity.js @@ -125,6 +125,9 @@ var updateConfig = function() { translationsForApplication = JSON.parse(translationsForApplication); for (lang in translationsForApplication) { var pathFileTranslate = pathResAndroidCordova+"values-"+lang+"/"; + if (lang == "default") { + pathFileTranslate = pathResAndroidCordova+"values/"; + } var objToXml; // already exist, get data. diff --git a/res/translations.json b/res/translations.json index 7124c8e..5fd127c 100644 --- a/res/translations.json +++ b/res/translations.json @@ -1,4 +1,10 @@ { + "default": { + "miniature": "Miniature", + "capture": "Capture", + "acceptePicture": "Valid the picture", + "declinePicture": "Decline the picture" + }, "fr": { "miniature": "Miniature", "capture": "Photo", diff --git a/src/android/CameraLauncher.java b/src/android/CameraLauncher.java index 47908af..9e9d208 100644 --- a/src/android/CameraLauncher.java +++ b/src/android/CameraLauncher.java @@ -74,19 +74,29 @@ public class CameraLauncher extends CordovaPlugin { TransferBigData.setImgBackgroundBase64OtherOrientation(imgBackgroundBase64OtherOrientation); } - intent.putExtra("miniature", args.getBoolean(2)); + // If we don't have a background image, disable miniature and opacity options. + if (TransferBigData.getImgBackgroundBase64() == null) { + intent.putExtra("miniature", false); + intent.putExtra("opacity", false); + } else { + intent.putExtra("miniature", args.getBoolean(2)); + intent.putExtra("opacity", args.getBoolean(7)); + } + intent.putExtra("saveInGallery", args.getBoolean(3)); intent.putExtra("cameraBackgroundColor", args.getString(4)); intent.putExtra("cameraBackgroundColorPressed", args.getString(5)); if (args.getInt(6) >= 0 && args.getInt(6) <= 100) { intent.putExtra("quality", args.getInt(6)); } - intent.putExtra("opacity", args.getBoolean(7)); intent.putExtra("startOrientation", this.cordova.getActivity().getResources().getConfiguration().orientation); intent.putExtra("defaultFlash", args.getInt(8)); intent.putExtra("switchFlash", args.getBoolean(9)); + intent.putExtra("defaultCamera", args.getInt(10)); + intent.putExtra("switchCamera", args.getBoolean(11)); + cordova.startActivityForResult((CordovaPlugin) this, intent, CameraLauncher.REQUEST_CODE); diff --git a/src/android/customCamera/res/drawable-hdpi/switch_camera.png b/src/android/customCamera/res/drawable-hdpi/switch_camera.png new file mode 100644 index 0000000..7a69823 Binary files /dev/null and b/src/android/customCamera/res/drawable-hdpi/switch_camera.png differ diff --git a/src/android/customCamera/res/layout/activity_camera_view.xml b/src/android/customCamera/res/layout/activity_camera_view.xml index 146fc05..955e92b 100644 --- a/src/android/customCamera/res/layout/activity_camera_view.xml +++ b/src/android/customCamera/res/layout/activity_camera_view.xml @@ -30,6 +30,15 @@ android:onClick="switchFlash" android:src="@drawable/flash" /> + + 0) { - try { - int cameraBackgroundColor = Color.parseColor(color); - backgroundGradient.setColor(cameraBackgroundColor); - } catch (IllegalArgumentException e) { - backgroundGradient.setColor(Color.TRANSPARENT); - } - } else { - backgroundGradient.setColor(Color.TRANSPARENT); - } - } /** Method onStart. Handle the zoom level seekBar and the camera orientation. */ @Override protected void onStart() { super.onStart(); - + + setBackground(); + // Init camera resource. - if (!initCameraResource()) { + if (!initCameraResource(null)) { return; } - - stateFlash = this.getIntent().getIntExtra("defaultFlash", CameraActivity.FLASH_DISABLE); - - updateStateFlash(stateFlash); - - int orientation = 0; - switch (getCustomRotation()) { - case 0: - orientation = CameraActivity.DEGREE_90; - break; - case 1: - orientation = CameraActivity.DEGREE_0; - break; - case 2: - orientation = CameraActivity.DEGREE_270; - break; - case 3: - orientation = CameraActivity.DEGREE_180; - break; - default: - break; - } - - customCamera.setDisplayOrientation(orientation); + // Adapt camera_preview to keep a ratio between screen' size and camera' size. DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); @@ -262,39 +261,37 @@ public class CameraActivity extends Activity { // Assign the render camera to the view CameraPreview myPreview = new CameraPreview(this, customCamera); cameraPreview.addView(myPreview); + + // Hide the switch camera button if the number of cameras is lower than 2. + if(Camera.getNumberOfCameras() < 2){ + ImageButton switchCamera = (ImageButton) findViewById(R.id.switchCamera); + switchCamera.setVisibility(View.INVISIBLE); + } + } + + /** To save some contains of the activity. */ + @Override + protected void onSaveInstanceState(Bundle outState) { + outState.putBoolean("modeMiniature", modeMiniature); + outState.putParcelable("photoTaken", photoTaken); + outState.putInt("stateFlash", stateFlash); + super.onSaveInstanceState(outState); + } - // The zoom bar progress - final SeekBar zoomLevel = (SeekBar) findViewById(R.id.zoomLevel); - final Camera.Parameters paramsCamera = customCamera.getParameters(); - final int zoom = paramsCamera.getZoom(); - int maxZoom = paramsCamera.getMaxZoom(); + /** To restore the contains saved on the method onSaveInstanceState(). */ + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + modeMiniature = savedInstanceState.getBoolean("modeMiniature"); + photoTaken = savedInstanceState.getParcelable("photoTaken"); + stateFlash = savedInstanceState.getInt("stateFlash"); + + if (modeMiniature) { + buttonMiniature(findViewById(R.id.miniature)); + } - zoomLevel.setMax(maxZoom); - zoomLevel.setProgress(zoom); - zoomLevel.setVisibility(View.VISIBLE); - - // Event on change zoom with the bar. - zoomLevel.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { - int progress = 0; - - @Override - public void onProgressChanged(SeekBar seekBar, int progresValue, - boolean fromUser) { - progress = progresValue; - int newZoom = (int) (zoom + progress); - zoomLevel.setProgress(newZoom); - paramsCamera.setZoom(newZoom); - customCamera.setParameters(paramsCamera); - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - } - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - } - }); + displayPicture(); + updateStateFlash(stateFlash); + super.onRestoreInstanceState(savedInstanceState); } /** Method to pause the activity. */ @@ -330,6 +327,25 @@ public class CameraActivity extends Activity { return true; } + + /** + * Set the background color of the camera button. + * @param color The color of the background. + */ + protected void setCameraBackgroundColor(String color) { + ImageButton imgIcon = (ImageButton)findViewById(R.id.capture); + GradientDrawable backgroundGradient = (GradientDrawable)imgIcon.getBackground(); + if (color.length() > 0) { + try { + int cameraBackgroundColor = Color.parseColor(color); + backgroundGradient.setColor(cameraBackgroundColor); + } catch (IllegalArgumentException e) { + backgroundGradient.setColor(Color.TRANSPARENT); + } + } else { + backgroundGradient.setColor(Color.TRANSPARENT); + } + } /** * Determine the space between the first two fingers. @@ -444,11 +460,6 @@ public class CameraActivity extends Activity { RelativeLayout.TRUE); background.setLayoutParams(paramsMiniature); - } else { - Button miniature = (Button) findViewById(R.id.miniature); - miniature.setVisibility(View.INVISIBLE); - SeekBar switchOpacity = (SeekBar) findViewById(R.id.switchOpacity); - switchOpacity.setVisibility(View.INVISIBLE); } } @@ -516,22 +527,35 @@ public class CameraActivity extends Activity { } /** - * Display the layout accept/decline photo + mask photo button. + * Manage to display buttons in function of picture is taken or not. */ - public void displayAcceptDeclineButtons() { - LinearLayout keepPhoto = (LinearLayout) findViewById(R.id.keepPhoto); - ImageButton photo = (ImageButton) findViewById(R.id.capture); - SeekBar zoomLevel = (SeekBar) findViewById(R.id.zoomLevel); - Button miniature = (Button) findViewById(R.id.miniature); - ImageView background = (ImageView) findViewById(R.id.background); - LayoutParams paramsLayoutMiniature = (LinearLayout.LayoutParams) miniature - .getLayoutParams(); + public void manageDisplayButtons() { + LinearLayout keepPhoto = (LinearLayout) findViewById(R.id.keepPhoto); + Button miniature = (Button) findViewById(R.id.miniature); + ImageButton flash = (ImageButton) findViewById(R.id.flash); + ImageButton photo = (ImageButton) findViewById(R.id.capture); + ImageButton switchCamera = (ImageButton) findViewById(R.id.switchCamera); + ImageView background = (ImageView) findViewById(R.id.background); + SeekBar zoomLevel = (SeekBar) findViewById(R.id.zoomLevel); + SeekBar switchOpacity = (SeekBar) findViewById(R.id.switchOpacity); + + LayoutParams paramsLayoutMiniature = (LinearLayout.LayoutParams) miniature.getLayoutParams(); + Camera.Parameters paramsCamera = customCamera.getParameters(); + + if (!this.getIntent().getBooleanExtra("miniature", true)) { + miniature.setVisibility(View.INVISIBLE); + } + if (!opacity) { + switchOpacity.setVisibility(View.INVISIBLE); + } if (photoTaken != null) { // Show/hide elements when a photo is taken keepPhoto.setVisibility(View.VISIBLE); photo.setVisibility(View.INVISIBLE); zoomLevel.setVisibility(View.INVISIBLE); + flash.setVisibility(View.INVISIBLE); + switchCamera.setVisibility(View.INVISIBLE); ((LinearLayout.LayoutParams) paramsLayoutMiniature).gravity = Gravity.TOP; miniature.setLayoutParams(paramsLayoutMiniature); @@ -544,7 +568,21 @@ public class CameraActivity extends Activity { // Show/hide elements when a photo is not taken keepPhoto.setVisibility(View.INVISIBLE); photo.setVisibility(View.VISIBLE); - zoomLevel.setVisibility(View.VISIBLE); + if (paramsCamera.isZoomSupported()) { + zoomLevel.setVisibility(View.VISIBLE); + } + + if (this.getIntent().getBooleanExtra("switchFlash", true)) { + flash.setVisibility(View.VISIBLE); + } else { + flash.setVisibility(View.INVISIBLE); + } + + if (this.getIntent().getBooleanExtra("switchCamera", true)) { + switchCamera.setVisibility(View.VISIBLE); + } else { + switchCamera.setVisibility(View.INVISIBLE); + } ((LinearLayout.LayoutParams) paramsLayoutMiniature).gravity = Gravity.BOTTOM; miniature.setLayoutParams(paramsLayoutMiniature); @@ -599,8 +637,6 @@ public class CameraActivity extends Activity { * Method to take picture. */ public void takePhoto() { - ImageButton flash = (ImageButton)findViewById(R.id.flash); - flash.setVisibility(View.INVISIBLE); // Handles the moment where picture is taken ShutterCallback shutterCallback = new ShutterCallback() { public void onShutter() { @@ -648,13 +684,12 @@ public class CameraActivity extends Activity { Matrix mat = new Matrix(); int defaultOrientation = getDeviceDefaultOrientation(); int orientationCamera = getOrientationOfCamera(); - int redirect = 0; + int redirect = CameraActivity.DEGREE_0; + switch (getCustomRotation()) { case 0: redirect = CameraActivity.DEGREE_90; - // If the device is in front camera by default - if (orientationCamera == 1 - && defaultOrientation == Configuration.ORIENTATION_PORTRAIT) { + if (ManagerCamera.currentCameraIsFacingFront() || orientationCamera == 1) { redirect = CameraActivity.DEGREE_270; } break; @@ -662,10 +697,11 @@ public class CameraActivity extends Activity { redirect = CameraActivity.DEGREE_0; break; case 2: - redirect = CameraActivity.DEGREE_270; - // If the device is in front camera by default - if (orientationCamera == 1 - && defaultOrientation == Configuration.ORIENTATION_PORTRAIT) { + // Only on device with landscape mode by default. + if (defaultOrientation == Configuration.ORIENTATION_LANDSCAPE) { + redirect = CameraActivity.DEGREE_270; + } + if (ManagerCamera.currentCameraIsFacingFront() || orientationCamera == 1) { redirect = CameraActivity.DEGREE_90; } break; @@ -676,6 +712,14 @@ public class CameraActivity extends Activity { break; } mat.postRotate(redirect); + // We execute a mirror to the matrix in case of front camera. + if (ManagerCamera.currentCameraIsFacingFront() || orientationCamera == 1 ) { + if (getCustomRotation() == 0 || getCustomRotation() == 2) { + mat.preScale(1.0f, -1.0f); + } else if (getCustomRotation() == 1 || getCustomRotation() == 3) { + mat.preScale(-1.0f, 1.0f); + } + } // Creation of the bitmap photoTaken = Bitmap.createBitmap(photoTaken, 0, 0, @@ -743,41 +787,14 @@ public class CameraActivity extends Activity { imgIcon.setEnabled(true); if (hasFlash()) { - ImageButton flash = (ImageButton)findViewById(R.id.flash); - flash.setVisibility(View.VISIBLE); + Camera.Parameters params = customCamera.getParameters(); + params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); + customCamera.setParameters(params); } - Camera.Parameters params = customCamera.getParameters(); - params.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); - customCamera.setParameters(params); photoTaken = null; displayPicture(); } - - /** To save some contains of the activity. */ - @Override - protected void onSaveInstanceState(Bundle outState) { - outState.putBoolean("modeMiniature", modeMiniature); - outState.putParcelable("photoTaken", photoTaken); - outState.putInt("stateFlash", stateFlash); - super.onSaveInstanceState(outState); - } - - /** To restore the contains saved on the method onSaveInstanceState(). */ - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { - modeMiniature = savedInstanceState.getBoolean("modeMiniature"); - photoTaken = savedInstanceState.getParcelable("photoTaken"); - stateFlash = savedInstanceState.getInt("stateFlash"); - - if (modeMiniature) { - buttonMiniature(findViewById(R.id.miniature)); - } - - displayPicture(); - updateStateFlash(stateFlash); - super.onRestoreInstanceState(savedInstanceState); - } /** To display or not the picture taken. */ protected void displayPicture() { @@ -799,7 +816,7 @@ public class CameraActivity extends Activity { preview.setVisibility(View.VISIBLE); } - displayAcceptDeclineButtons(); + manageDisplayButtons(); } /** @@ -937,12 +954,10 @@ public class CameraActivity extends Activity { imgResource = R.drawable.flash_auto; break; } - + flash.setImageResource(imgResource); customCamera.setParameters(params); - } else { - flash.setVisibility(View.INVISIBLE); } } @@ -964,8 +979,6 @@ public class CameraActivity extends Activity { Camera.Parameters params = customCamera.getParameters(); params.setFlashMode(mode); customCamera.setParameters(params); - } else { - flash.setVisibility(View.INVISIBLE); } } @@ -990,4 +1003,17 @@ public class CameraActivity extends Activity { (supportedFlashModes.size() == 1 && supportedFlashModes.get(0).equals(Camera.Parameters.FLASH_MODE_OFF)) ); } + + /** + * To change the active camera. + * @param view The current view. + */ + public void switchCamera(View view) { + int oppositeCamera = ManagerCamera.determineOppositeCamera(); + initCameraResource(oppositeCamera); + FrameLayout cameraPreview = (FrameLayout) findViewById(R.id.camera_preview); + cameraPreview.removeAllViews(); + CameraPreview myPreview = new CameraPreview(this, customCamera); + cameraPreview.addView(myPreview); + } } diff --git a/src/android/customCamera/src/org/geneanet/customcamera/ManagerCamera.java b/src/android/customCamera/src/org/geneanet/customcamera/ManagerCamera.java index cda4e23..c6fe0ce 100644 --- a/src/android/customCamera/src/org/geneanet/customcamera/ManagerCamera.java +++ b/src/android/customCamera/src/org/geneanet/customcamera/ManagerCamera.java @@ -1,7 +1,10 @@ package org.geneanet.customcamera; +import android.app.Activity; import android.hardware.Camera; +import android.hardware.Camera.CameraInfo; import android.util.Log; +import android.view.Surface; /** * Manage camera resource. @@ -14,26 +17,29 @@ public class ManagerCamera { public static final int LANDSCAPE = 1; public static final int PORTRAIT_INVERSED = 2; public static final int LANDSCAPE_INVERSED = 3; + private static Integer currentCameraPosition = null; /** * A safe way to get an instance of the Camera object. * * @return Camera | null */ - public static Camera getCameraInstance() { + public static Camera getCameraInstance(int position) { // If camera is already instanced and available, return this resource. - if (ManagerCamera.mCamera != null) { + if (ManagerCamera.mCamera != null && position == currentCameraPosition) { return ManagerCamera.mCamera; + } else if (ManagerCamera.mCamera != null) { + clearCameraAccess(); } // Start back camera. Camera cam = null; try { - cam = Camera.open(0); + cam = Camera.open(position); + currentCameraPosition = position; } catch (RuntimeException e) { Log.e("customCamera", "Can't open the camera back."); } - ManagerCamera.mCamera = cam; return cam; // returns null if camera is unavailable @@ -49,4 +55,143 @@ public class ManagerCamera { ManagerCamera.mCamera = null; } } + + /** + * Return the value of the position of the front camera. + * + * @return int + */ + public static int determinePositionFrontCamera() { + return determineCamera(Camera.CameraInfo.CAMERA_FACING_FRONT); + } + + /** + * Return the value of the position of the back camera. + * + * @return int + */ + public static int determinePositionBackCamera() { + return determineCamera(Camera.CameraInfo.CAMERA_FACING_BACK); + } + + /** + * Determine the opposite camera of which currently in use. + * + * @return int. + */ + public static int determineOppositeCamera() { + if (getCurrentFacingCamera() == Camera.CameraInfo.CAMERA_FACING_BACK) { + return determinePositionFrontCamera(); + } else { + return determinePositionBackCamera(); + } + } + + /** + * Determine the cameraId of the camera currently in use. + * + * @param position Back or front camera. + * + * @return the cameraId of the current camera if it exists. + */ + protected static Integer determineCamera(int position) { + CameraInfo info = new Camera.CameraInfo(); + if (Camera.getNumberOfCameras() == 0) { + return null; + } + if (Camera.getNumberOfCameras() == 1) { + return 0; + } + for (int i = 0; i < Camera.getNumberOfCameras(); i++) { + Camera.getCameraInfo(i, info); + if (info.facing == position) { + return i; + } + } + + return 0; + } + + /** + * Get the current camera. + * + * @return the value of currentCameraPosition. + */ + private static int getCurrentFacingCamera() { + CameraInfo info = new Camera.CameraInfo(); + Camera.getCameraInfo(currentCameraPosition, info); + + return info.facing; + } + + /** + * Determine if the current camera is front. + * + * @return True if the current camera is front. Else return false. + */ + public static boolean currentCameraIsFacingBack() { + if (getCurrentFacingCamera() == Camera.CameraInfo.CAMERA_FACING_BACK) { + return true; + } + return false; + } + + /** + * Determine if the camera is back. + * + * @return True if the current camera is back. Else return false. + */ + public static boolean currentCameraIsFacingFront() { + if (getCurrentFacingCamera() == Camera.CameraInfo.CAMERA_FACING_FRONT) { + return true; + } + return false; + } + + /** + * To stabilize the orientation of the camera preview. + * @param activity + * @param cameraId + * @param camera + */ + public static void setCameraDisplayOrientation(Activity activity) { + CameraInfo info = new Camera.CameraInfo(); + Camera.getCameraInfo(ManagerCamera.currentCameraPosition, info); + int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); + int degrees = 0; + switch (rotation) { + case Surface.ROTATION_0: degrees = 0; break; + case Surface.ROTATION_90: degrees = 90; break; + case Surface.ROTATION_180: degrees = 180; break; + case Surface.ROTATION_270: degrees = 270; break; + default : break; + } + + int result; + if (info.facing == CameraInfo.CAMERA_FACING_FRONT) { + result = (info.orientation + degrees) % 360; + result = (360 - result) % 360; // compensate the mirror + } else { // back-facing + result = (info.orientation - degrees + 360) % 360; + } + ManagerCamera.mCamera.setDisplayOrientation(result); + } + + /** + * Get the value of currentCameraPosition. + * + * @return Integer. + */ + public static int getCurrentCameraPosition() { + return ManagerCamera.currentCameraPosition; + } + + /** + * Get the value of mCamera. + * + * @return Camera. + */ + public static Camera getCurrentCameraResource() { + return ManagerCamera.mCamera; + } } diff --git a/www/customCamera.js b/www/customCamera.js index b179b79..92137fb 100644 --- a/www/customCamera.js +++ b/www/customCamera.js @@ -8,6 +8,7 @@ function CustomCameraExport() {} CustomCameraExport.prototype.FlashModes = {DISABLE: 0, ACTIVE: 1, AUTO: 2}; + CustomCameraExport.prototype.CameraFacings = {BACK: 0, FRONT: 1}; /** * Start custom camera. @@ -27,8 +28,10 @@ // To get supported color formats, go to see method parseColor : http://developer.android.com/reference/android/graphics/Color.html#parseColor(java.lang.String) quality: 100, // picture's quality : range 0 - 100 : http://developer.android.com/reference/android/graphics/Bitmap.html#compress(android.graphics.Bitmap.CompressFormat, int, java.io.OutputStream) (parameter "quality") opacity: true, // active or disable the opacity function. - defaultFlash: this.FlashModes.DISABLE, // default state for flash. Corrects values = 0 (disable) / 1 (active) / 2 (auto) - switchFlash: true // active or disable the switch flash button. + defaultFlash: this.FlashModes.DISABLE, // default state for flash. See CustomCamera.FlashModes for corrects values. + switchFlash: true, // active or disable the switch flash button. + defaultCamera: this.CameraFacings.BACK, // default camera used. See CustomCamera.CameraFacings for corrects values. + switchCamera: true // active or disable the switch camera button. }; for (var nameOption in defaultOptions) { @@ -60,7 +63,9 @@ options.quality, options.opacity, options.defaultFlash, - options.switchFlash + options.switchFlash, + options.defaultCamera, + options.switchCamera ] ); };