Return-Path: X-Original-To: apmail-cordova-commits-archive@www.apache.org Delivered-To: apmail-cordova-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B477810675 for ; Thu, 13 Feb 2014 19:58:27 +0000 (UTC) Received: (qmail 50328 invoked by uid 500); 13 Feb 2014 19:58:26 -0000 Delivered-To: apmail-cordova-commits-archive@cordova.apache.org Received: (qmail 50291 invoked by uid 500); 13 Feb 2014 19:58:26 -0000 Mailing-List: contact commits-help@cordova.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cordova.apache.org Delivered-To: mailing list commits@cordova.apache.org Received: (qmail 50283 invoked by uid 99); 13 Feb 2014 19:58:26 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 13 Feb 2014 19:58:26 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 1D12C8A95F4; Thu, 13 Feb 2014 19:58:26 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: agrieve@apache.org To: commits@cordova.apache.org Date: Thu, 13 Feb 2014 19:58:26 -0000 Message-Id: <7535a465490e4a5185b4743506da7e2d@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/2] git commit: Refactor onActivityResult Updated Branches: refs/heads/dev ab5c95743 -> 4ae441485 Refactor onActivityResult Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/commit/61ba9cca Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/tree/61ba9cca Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/diff/61ba9cca Branch: refs/heads/dev Commit: 61ba9cca4b8d630c259658187ab7137e5cf952d8 Parents: ab5c957 Author: Clément Vollet Authored: Tue Jan 28 12:07:23 2014 +0100 Committer: Andrew Grieve Committed: Thu Feb 13 13:24:41 2014 -0500 ---------------------------------------------------------------------- src/android/CameraLauncher.java | 409 +++++++++++++++++++---------------- 1 file changed, 217 insertions(+), 192 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/61ba9cca/src/android/CameraLauncher.java ---------------------------------------------------------------------- diff --git a/src/android/CameraLauncher.java b/src/android/CameraLauncher.java index 0dd247b..4e41d4b 100755 --- a/src/android/CameraLauncher.java +++ b/src/android/CameraLauncher.java @@ -58,7 +58,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect private static final int DATA_URL = 0; // Return base64 encoded string private static final int FILE_URI = 1; // Return file uri (content://media/external/images/media/2 for Android) - private static final int NATIVE_URI = 2; // On Android, this is the same as FILE_URI + private static final int NATIVE_URI = 2; // On Android, this is the same as FILE_URI private static final int PHOTOLIBRARY = 0; // Choose image from picture library (same as SAVEDPHOTOALBUM for Android) private static final int CAMERA = 1; // Take picture from camera @@ -95,10 +95,10 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect /** * Executes the request and returns PluginResult. * - * @param action The action to execute. - * @param args JSONArry of arguments for the plugin. + * @param action The action to execute. + * @param args JSONArry of arguments for the plugin. * @param callbackContext The callback id used when calling back into JavaScript. - * @return A PluginResult object with a status and message. + * @return A PluginResult object with a status and message. */ public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { this.callbackContext = callbackContext; @@ -265,115 +265,237 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect } /** - * Called when the camera view exits. + * Applies all needed transformation to the image received from the camera. * - * @param requestCode The request code originally supplied to startActivityForResult(), - * allowing you to identify who this result came from. - * @param resultCode The integer result code returned by the child activity through its setResult(). + * @param destType In which form should we return the image * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). */ - public void onActivityResult(int requestCode, int resultCode, Intent intent) { - - // Get src and dest types from request code - int srcType = (requestCode / 16) - 1; - int destType = (requestCode % 16) - 1; + private void processResultFromCamera(int destType, Intent intent) throws IOException { int rotate = 0; - // If CAMERA - if (srcType == CAMERA) { - // If image available - if (resultCode == Activity.RESULT_OK) { - try { - // Create an ExifHelper to save the exif data that is lost during compression - ExifHelper exif = new ExifHelper(); - try { - if (this.encodingType == JPEG) { - exif.createInFile(getTempDirectoryPath() + "/.Pic.jpg"); - exif.readExifData(); - rotate = exif.getOrientation(); - } - } catch (IOException e) { - e.printStackTrace(); - } + // Create an ExifHelper to save the exif data that is lost during compression + ExifHelper exif = new ExifHelper(); + try { + if (this.encodingType == JPEG) { + exif.createInFile(getTempDirectoryPath() + "/.Pic.jpg"); + exif.readExifData(); + rotate = exif.getOrientation(); + } + } catch (IOException e) { + e.printStackTrace(); + } - Bitmap bitmap = null; - Uri uri = null; + Bitmap bitmap = null; + Uri uri = null; - // If sending base64 image back - if (destType == DATA_URL) { - bitmap = getScaledBitmap(FileHelper.stripFileProtocol(imageUri.toString())); - if (bitmap == null) { - // Try to get the bitmap from intent. - bitmap = (Bitmap)intent.getExtras().get("data"); - } - - // Double-check the bitmap. - if (bitmap == null) { - Log.d(LOG_TAG, "I either have a null image path or bitmap"); - this.failPicture("Unable to create bitmap!"); - return; - } + // If sending base64 image back + if (destType == DATA_URL) { + bitmap = getScaledBitmap(FileHelper.stripFileProtocol(imageUri.toString())); + if (bitmap == null) { + // Try to get the bitmap from intent. + bitmap = (Bitmap)intent.getExtras().get("data"); + } + + // Double-check the bitmap. + if (bitmap == null) { + Log.d(LOG_TAG, "I either have a null image path or bitmap"); + this.failPicture("Unable to create bitmap!"); + return; + } - if (rotate != 0 && this.correctOrientation) { - bitmap = getRotatedBitmap(rotate, bitmap, exif); - } + if (rotate != 0 && this.correctOrientation) { + bitmap = getRotatedBitmap(rotate, bitmap, exif); + } + + this.processPicture(bitmap); + checkForDuplicateImage(DATA_URL); + } + + // If sending filename back + else if (destType == FILE_URI || destType == NATIVE_URI) { + if (this.saveToPhotoAlbum) { + Uri inputUri = getUriFromMediaStore(); + //Just because we have a media URI doesn't mean we have a real file, we need to make it + uri = Uri.fromFile(new File(FileHelper.getRealPath(inputUri, this.cordova))); + } else { + uri = Uri.fromFile(new File(getTempDirectoryPath(), System.currentTimeMillis() + ".jpg")); + } - this.processPicture(bitmap); - checkForDuplicateImage(DATA_URL); + if (uri == null) { + this.failPicture("Error capturing image - no media storage found."); + } + + // If all this is true we shouldn't compress the image. + if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 && + !this.correctOrientation) { + writeUncompressedImage(uri); + + this.callbackContext.success(uri.toString()); + } else { + bitmap = getScaledBitmap(FileHelper.stripFileProtocol(imageUri.toString())); + + if (rotate != 0 && this.correctOrientation) { + bitmap = getRotatedBitmap(rotate, bitmap, exif); + } + + // Add compressed version of captured image to returned media store Uri + OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); + bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); + os.close(); + + // Restore exif data to file + if (this.encodingType == JPEG) { + String exifPath; + if (this.saveToPhotoAlbum) { + exifPath = FileHelper.getRealPath(uri, this.cordova); + } else { + exifPath = uri.getPath(); } + exif.createOutFile(exifPath); + exif.writeExifData(); + } - // If sending filename back - else if (destType == FILE_URI || destType == NATIVE_URI) { - if (this.saveToPhotoAlbum) { - Uri inputUri = getUriFromMediaStore(); - //Just because we have a media URI doesn't mean we have a real file, we need to make it - uri = Uri.fromFile(new File(FileHelper.getRealPath(inputUri, this.cordova))); - } else { - uri = Uri.fromFile(new File(getTempDirectoryPath(), System.currentTimeMillis() + ".jpg")); - } + } + // Send Uri back to JavaScript for viewing image + this.callbackContext.success(uri.toString()); + } - if (uri == null) { - this.failPicture("Error capturing image - no media storage found."); - } + this.cleanup(FILE_URI, this.imageUri, uri, bitmap); + bitmap = null; + } + + private String ouputResizedBitmap(Bitmap bitmap, Uri uri) throws IOException { + // Create an ExifHelper to save the exif data that is lost during compression + String resizePath = getTempDirectoryPath() + "/resize.jpg"; + // Some content: URIs do not map to file paths (e.g. picasa). + String realPath = FileHelper.getRealPath(uri, this.cordova); + ExifHelper exif = new ExifHelper(); + if (realPath != null && this.encodingType == JPEG) { + try { + exif.createInFile(realPath); + exif.readExifData(); + rotate = exif.getOrientation(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + OutputStream os = new FileOutputStream(resizePath); + bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); + os.close(); + + // Restore exif data to file + if (realPath != null && this.encodingType == JPEG) { + exif.createOutFile(resizePath); + exif.writeExifData(); + } + return resizePath; + } + + /** + * Applies all needed transformation to the image received from the gallery. + * + * @param destType In which form should we return the image + * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). + */ + private void processResultFromGallery(int destType, Intent intent) { + Uri uri = intent.getData(); + int rotate = 0; - // If all this is true we shouldn't compress the image. - if (this.targetHeight == -1 && this.targetWidth == -1 && this.mQuality == 100 && - !this.correctOrientation) { - writeUncompressedImage(uri); - - this.callbackContext.success(uri.toString()); - } else { - bitmap = getScaledBitmap(FileHelper.stripFileProtocol(imageUri.toString())); - - if (rotate != 0 && this.correctOrientation) { - bitmap = getRotatedBitmap(rotate, bitmap, exif); - } - - // Add compressed version of captured image to returned media store Uri - OutputStream os = this.cordova.getActivity().getContentResolver().openOutputStream(uri); - bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); - os.close(); - - // Restore exif data to file - if (this.encodingType == JPEG) { - String exifPath; - if (this.saveToPhotoAlbum) { - exifPath = FileHelper.getRealPath(uri, this.cordova); - } else { - exifPath = uri.getPath(); - } - exif.createOutFile(exifPath); - exif.writeExifData(); - } + // If you ask for video or all media type you will automatically get back a file URI + // and there will be no attempt to resize any returned data + if (this.mediaType != PICTURE) { + this.callbackContext.success(uri.toString()); + } + else { + // This is a special case to just return the path as no scaling, + // rotating, nor compressing needs to be done + if (this.targetHeight == -1 && this.targetWidth == -1 && + (destType == FILE_URI || destType == NATIVE_URI) && !this.correctOrientation) { + this.callbackContext.success(uri.toString()); + } else { + String uriString = uri.toString(); + // Get the path to the image. Makes loading so much easier. + String mimeType = FileHelper.getMimeType(uriString, this.cordova); + // If we don't have a valid image so quit. + if (!("image/jpeg".equalsIgnoreCase(mimeType) || "image/png".equalsIgnoreCase(mimeType))) { + Log.d(LOG_TAG, "I either have a null image path or bitmap"); + this.failPicture("Unable to retrieve path to picture!"); + return; + } + Bitmap bitmap = null; + try { + bitmap = getScaledBitmap(uriString); + } catch (IOException e) { + e.printStackTrace(); + } + if (bitmap == null) { + Log.d(LOG_TAG, "I either have a null image path or bitmap"); + this.failPicture("Unable to create bitmap!"); + return; + } + if (this.correctOrientation) { + rotate = getImageOrientation(uri); + if (rotate != 0) { + Matrix matrix = new Matrix(); + matrix.setRotate(rotate); + bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); + } + } + + // If sending base64 image back + if (destType == DATA_URL) { + this.processPicture(bitmap); + } + + // If sending filename back + else if (destType == FILE_URI || destType == NATIVE_URI) { + // Do we need to scale the returned file + if (this.targetHeight > 0 && this.targetWidth > 0) { + try { + String resizePath = this.ouputResizedBitmap(bitmap, uri); + // The resized image is cached by the app in order to get around this and not have to delete you + // application cache I'm adding the current system time to the end of the file url. + this.callbackContext.success("file://" + resizePath + "?" + System.currentTimeMillis()); + } catch (Exception e) { + e.printStackTrace(); + this.failPicture("Error retrieving image."); } - // Send Uri back to JavaScript for viewing image + } + else { this.callbackContext.success(uri.toString()); } - - this.cleanup(FILE_URI, this.imageUri, uri, bitmap); + } + if (bitmap != null) { + bitmap.recycle(); bitmap = null; + } + System.gc(); + } + } + } + + /** + * Called when the camera view exits. + * + * @param requestCode The request code originally supplied to startActivityForResult(), + * allowing you to identify who this result came from. + * @param resultCode The integer result code returned by the child activity through its setResult(). + * @param intent An Intent, which can return result data to the caller (various data can be attached to Intent "extras"). + */ + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + + // Get src and dest types from request code + int srcType = (requestCode / 16) - 1; + int destType = (requestCode % 16) - 1; + // If CAMERA + if (srcType == CAMERA) { + // If image available + if (resultCode == Activity.RESULT_OK) { + try { + this.processResultFromCamera(destType, intent); } catch (IOException e) { e.printStackTrace(); this.failPicture("Error capturing image."); @@ -394,104 +516,7 @@ public class CameraLauncher extends CordovaPlugin implements MediaScannerConnect // If retrieving photo from library else if ((srcType == PHOTOLIBRARY) || (srcType == SAVEDPHOTOALBUM)) { if (resultCode == Activity.RESULT_OK) { - Uri uri = intent.getData(); - - // If you ask for video or all media type you will automatically get back a file URI - // and there will be no attempt to resize any returned data - if (this.mediaType != PICTURE) { - this.callbackContext.success(uri.toString()); - } - else { - // This is a special case to just return the path as no scaling, - // rotating, nor compressing needs to be done - if (this.targetHeight == -1 && this.targetWidth == -1 && - (destType == FILE_URI || destType == NATIVE_URI) && !this.correctOrientation) { - this.callbackContext.success(uri.toString()); - } else { - String uriString = uri.toString(); - // Get the path to the image. Makes loading so much easier. - String mimeType = FileHelper.getMimeType(uriString, this.cordova); - // If we don't have a valid image so quit. - if (!("image/jpeg".equalsIgnoreCase(mimeType) || "image/png".equalsIgnoreCase(mimeType))) { - Log.d(LOG_TAG, "I either have a null image path or bitmap"); - this.failPicture("Unable to retrieve path to picture!"); - return; - } - Bitmap bitmap = null; - try { - bitmap = getScaledBitmap(uriString); - } catch (IOException e) { - e.printStackTrace(); - } - if (bitmap == null) { - Log.d(LOG_TAG, "I either have a null image path or bitmap"); - this.failPicture("Unable to create bitmap!"); - return; - } - - if (this.correctOrientation) { - rotate = getImageOrientation(uri); - if (rotate != 0) { - Matrix matrix = new Matrix(); - matrix.setRotate(rotate); - bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); - } - } - - // If sending base64 image back - if (destType == DATA_URL) { - this.processPicture(bitmap); - } - - // If sending filename back - else if (destType == FILE_URI || destType == NATIVE_URI) { - // Do we need to scale the returned file - if (this.targetHeight > 0 && this.targetWidth > 0) { - try { - // Create an ExifHelper to save the exif data that is lost during compression - String resizePath = getTempDirectoryPath() + "/resize.jpg"; - // Some content: URIs do not map to file paths (e.g. picasa). - String realPath = FileHelper.getRealPath(uri, this.cordova); - ExifHelper exif = new ExifHelper(); - if (realPath != null && this.encodingType == JPEG) { - try { - exif.createInFile(realPath); - exif.readExifData(); - rotate = exif.getOrientation(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - OutputStream os = new FileOutputStream(resizePath); - bitmap.compress(Bitmap.CompressFormat.JPEG, this.mQuality, os); - os.close(); - - // Restore exif data to file - if (realPath != null && this.encodingType == JPEG) { - exif.createOutFile(resizePath); - exif.writeExifData(); - } - - // The resized image is cached by the app in order to get around this and not have to delete you - // application cache I'm adding the current system time to the end of the file url. - this.callbackContext.success("file://" + resizePath + "?" + System.currentTimeMillis()); - } catch (Exception e) { - e.printStackTrace(); - this.failPicture("Error retrieving image."); - } - } - else { - this.callbackContext.success(uri.toString()); - } - } - if (bitmap != null) { - bitmap.recycle(); - bitmap = null; - } - System.gc(); - } - } + this.processResultFromGallery(destType, intent) } else if (resultCode == Activity.RESULT_CANCELED) { this.failPicture("Selection cancelled.");