diff --git a/src/android/Library/src/MultiImageChooserActivity.java b/src/android/Library/src/MultiImageChooserActivity.java index e694460..5263277 100644 --- a/src/android/Library/src/MultiImageChooserActivity.java +++ b/src/android/Library/src/MultiImageChooserActivity.java @@ -483,6 +483,8 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi private class ResizeImagesTask extends AsyncTask>, Void, ArrayList> { + private Exception asyncTaskError = null; + @Override protected ArrayList doInBackground(Set>... fileSets) { Set> fileNames = fileSets[0]; @@ -493,6 +495,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi while(i.hasNext()) { Entry imageInfo = i.next(); File file = new File(imageInfo.getKey()); + int rotate = imageInfo.getValue().intValue(); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 1; options.inJustDecodeBounds = true; @@ -506,41 +509,43 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi int inSampleSize = calculateInSampleSize(options, finalWidth, finalHeight); options = new BitmapFactory.Options(); options.inSampleSize = inSampleSize; - bmp = BitmapFactory.decodeFile(file.getAbsolutePath(), options); - if (bmp == null) { - throw new IOException("The image file could not be opened."); + try { + bmp = this.tryToGetBitmap(file, options, rotate, true); + } catch (OutOfMemoryError e) { + options.inSampleSize = calculateNextSampleSize(options.inSampleSize); + try { + bmp = this.tryToGetBitmap(file, options, rotate, false); + } catch (OutOfMemoryError e2) { + throw new IOException("Unable to load image into memory."); + } } - scale = calculateScale(options.outWidth, options.outHeight); - bmp = this.getResizedBitmap(bmp, scale); } else { try { - bmp = BitmapFactory.decodeFile(file.getAbsolutePath()); + bmp = this.tryToGetBitmap(file, null, rotate, false); } catch(OutOfMemoryError e) { options = new BitmapFactory.Options(); options.inSampleSize = 2; try { - bmp = BitmapFactory.decodeFile(file.getAbsolutePath(), options); + bmp = this.tryToGetBitmap(file, options, rotate, false); } catch(OutOfMemoryError e2) { options = new BitmapFactory.Options(); options.inSampleSize = 4; - bmp = BitmapFactory.decodeFile(file.getAbsolutePath(), options); + try { + bmp = this.tryToGetBitmap(file, options, rotate, false); + } catch (OutOfMemoryError e3) { + throw new IOException("Unable to load image into memory."); + } } } } - - int rotate = imageInfo.getValue().intValue(); - if (rotate != 0) { - Matrix matrix = new Matrix(); - matrix.setRotate(rotate); - bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true); - } - + file = this.storeImage(bmp, file.getName()); al.add(Uri.fromFile(file).toString()); } return al; } catch(IOException e) { try { + asyncTaskError = e; for (int i = 0; i < al.size(); i++) { URI uri = new URI(al.get(i)); File file = new File(uri); @@ -557,22 +562,49 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi @Override protected void onPostExecute(ArrayList al) { Intent data = new Intent(); - - if (al.size() > 0) { + + if (asyncTaskError != null) { + Bundle res = new Bundle(); + res.putString("ERRORMESSAGE", asyncTaskError.getMessage()); + data.putExtras(res); + setResult(RESULT_CANCELED, data); + } else if (al.size() > 0) { Bundle res = new Bundle(); res.putStringArrayList("MULTIPLEFILENAMES", al); if (imagecursor != null) { res.putInt("TOTALFILES", imagecursor.getCount()); } - data.putExtras(res); setResult(RESULT_OK, data); } else { setResult(RESULT_CANCELED, data); } + progress.dismiss(); finish(); } + + private Bitmap tryToGetBitmap(File file, BitmapFactory.Options options, int rotate, boolean shouldScale) throws IOException, OutOfMemoryError { + Bitmap bmp; + if (options == null) { + bmp = BitmapFactory.decodeFile(file.getAbsolutePath()); + } else { + bmp = BitmapFactory.decodeFile(file.getAbsolutePath(), options); + } + if (bmp == null) { + throw new IOException("The image file could not be opened."); + } + if (options != null && shouldScale) { + float scale = calculateScale(options.outWidth, options.outHeight); + bmp = this.getResizedBitmap(bmp, scale); + } + if (rotate != 0) { + Matrix matrix = new Matrix(); + matrix.setRotate(rotate); + bmp = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true); + } + return bmp; + } /* * The following functions are originally from @@ -631,6 +663,11 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi return inSampleSize; } + + private int calculateNextSampleSize(int sampleSize) { + double logBaseTwo = (int)(Math.log(sampleSize) / Math.log(2)); + return (int)Math.pow(logBaseTwo + 1, 2); + } private float calculateScale(int width, int height) { float widthScale = 1.0f; diff --git a/src/android/com/synconset/ImagePicker/ImagePicker.java b/src/android/com/synconset/ImagePicker/ImagePicker.java index 4a3874f..2f4939a 100644 --- a/src/android/com/synconset/ImagePicker/ImagePicker.java +++ b/src/android/com/synconset/ImagePicker/ImagePicker.java @@ -17,53 +17,56 @@ import android.content.Intent; import android.util.Log; public class ImagePicker extends CordovaPlugin { - public static String TAG = "ImagePicker"; - - private CallbackContext callbackContext; - private JSONObject params; - + public static String TAG = "ImagePicker"; + + private CallbackContext callbackContext; + private JSONObject params; + public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException { - this.callbackContext = callbackContext; - this.params = args.getJSONObject(0); + this.callbackContext = callbackContext; + this.params = args.getJSONObject(0); if (action.equals("getPictures")) { Intent intent = new Intent(cordova.getActivity(), MultiImageChooserActivity.class); int max = 20; int desiredWidth = 0; - int desiredHeight = 0; - int quality = 100; + int desiredHeight = 0; + int quality = 100; if (this.params.has("maximumImagesCount")) { - max = this.params.getInt("maximumImagesCount"); + max = this.params.getInt("maximumImagesCount"); } if (this.params.has("width")) { - desiredWidth = this.params.getInt("width"); + desiredWidth = this.params.getInt("width"); } if (this.params.has("height")) { - desiredWidth = this.params.getInt("height"); + desiredWidth = this.params.getInt("height"); } if (this.params.has("quality")) { - quality = this.params.getInt("quality"); - } + quality = this.params.getInt("quality"); + } intent.putExtra("MAX_IMAGES", max); intent.putExtra("WIDTH", desiredWidth); intent.putExtra("HEIGHT", desiredHeight); intent.putExtra("QUALITY", quality); - if (this.cordova != null) { - this.cordova.startActivityForResult((CordovaPlugin) this, intent, 0); - } + if (this.cordova != null) { + this.cordova.startActivityForResult((CordovaPlugin) this, intent, 0); + } } return true; } public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == Activity.RESULT_OK && data != null) { - ArrayList fileNames = data.getStringArrayListExtra("MULTIPLEFILENAMES"); - JSONArray res = new JSONArray(fileNames); - this.callbackContext.success(res); - } else if (resultCode == Activity.RESULT_CANCELED) { - JSONArray res = new JSONArray(); - this.callbackContext.success(res); - } else { - this.callbackContext.error("No images selected"); - } + if (resultCode == Activity.RESULT_OK && data != null) { + ArrayList fileNames = data.getStringArrayListExtra("MULTIPLEFILENAMES"); + JSONArray res = new JSONArray(fileNames); + this.callbackContext.success(res); + } else if (resultCode == Activity.RESULT_CANCELED && data != null) { + String error = data.getStringExtra("ERRORMESSAGE"); + this.callbackContext.error(error); + } else if (resultCode == Activity.RESULT_CANCELED) { + JSONArray res = new JSONArray(); + this.callbackContext.success(res); + } else { + this.callbackContext.error("No images selected"); + } } } \ No newline at end of file