diff --git a/src/android/Library/libs/commons-io-2.4.jar b/src/android/Library/libs/commons-io-2.4.jar new file mode 100644 index 0000000..90035a4 Binary files /dev/null and b/src/android/Library/libs/commons-io-2.4.jar differ diff --git a/src/android/Library/libs/gson-2.3.1.jar b/src/android/Library/libs/gson-2.3.1.jar new file mode 100644 index 0000000..250132c Binary files /dev/null and b/src/android/Library/libs/gson-2.3.1.jar differ diff --git a/src/android/Library/src/FileNameItem.java b/src/android/Library/src/FileNameItem.java new file mode 100644 index 0000000..ea31b05 --- /dev/null +++ b/src/android/Library/src/FileNameItem.java @@ -0,0 +1,65 @@ +package com.synconset; + +import org.json.JSONException; +import org.json.JSONObject; + +import android.os.Parcel; +import android.os.Parcelable; + +public class FileNameItem implements Parcelable{ + public String thumb; + public String original; + public Integer rotation; + + public FileNameItem(){ + super(); + } + + public FileNameItem(Parcel in) { + super(); + readFromParcel(in); + } + + public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { + public FileNameItem createFromParcel(Parcel in) { + return new FileNameItem(in); + } + + public FileNameItem[] newArray(int size) { + + return new FileNameItem[size]; + } + + }; + + public void readFromParcel(Parcel in) { + thumb = in.readString(); + original = in.readString(); + rotation = in.readInt(); + } + + @Override + public int describeContents() { + // TODO Auto-generated method stub + return 0; + } + @Override + public void writeToParcel(Parcel dest, int flags ) { + // TODO Auto-generated method stub + dest.writeString(thumb); + dest.writeString(original); + dest.writeInt(rotation); + } + + /*public JSONObject getJSONObject() { + JSONObject obj = new JSONObject(); + try { + obj.put("thumb", thumb); + obj.put("original", orginal); + obj.put("rotation", rotation); + } catch (JSONException e) { + //trace("DefaultListItem.toString JSONException: "+e.getMessage()); + } + return obj; + }*/ +} diff --git a/src/android/Library/src/ImageFetcher.java b/src/android/Library/src/ImageFetcher.java index 88255bd..9564df2 100644 --- a/src/android/Library/src/ImageFetcher.java +++ b/src/android/Library/src/ImageFetcher.java @@ -16,23 +16,32 @@ package com.synconset; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; +import org.apache.commons.io.FileUtils; + import android.content.Context; import android.graphics.Bitmap; +import android.graphics.Bitmap.CompressFormat; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.Matrix; import android.os.AsyncTask; import android.os.Build; +import android.os.Environment; import android.os.Handler; import android.provider.MediaStore; import android.util.Log; @@ -54,13 +63,43 @@ import android.widget.ImageView; * performance. */ public class ImageFetcher { - + private int colWidth; private long origId; private ExecutorService executor; - public ImageFetcher() { + File dir_thumb; + private Context context; + private Map thumbnails = new HashMap(); + + public ImageFetcher( Context ct ) { + context = ct; executor = Executors.newCachedThreadPool(); + + dir_thumb = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES),"thumb"); + if( !dir_thumb.isDirectory() && !dir_thumb.mkdir() ){ + // failed + } + + try { + FileUtils.cleanDirectory(dir_thumb); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + /** + * Get Thumb URL + * @param id + * @return + */ + public String getThumbFilePath( Integer id ){ + + String url = thumbnails.get(id); + + return url; } public void fetch(Integer id, ImageView imageView, int colWidth, int rotate) { @@ -230,6 +269,10 @@ public class ImageFetcher { if (isCancelled()) { bitmap = null; } + + // store bitmap to private storage + storeBitmapToPrivate(position, bitmap); + addBitmapToCache(position, bitmap); if (imageViewReference != null) { ImageView imageView = imageViewReference.get(); @@ -245,6 +288,86 @@ public class ImageFetcher { } } } + + /** + * Save Thumbnail to private storage. + */ + boolean storeBitmapToPrivate( Integer position, Bitmap bitmap ){ + + if( thumbnails.containsKey(position) ){ + return true; + } + + /*String state = Environment.getExternalStorageState(); + if ( !Environment.MEDIA_MOUNTED.equals(state)) { + return false; + } + */ + + if( !dir_thumb.isDirectory() ){ + return false; + } + + String state = Environment.getExternalStorageState(); + if ( !Environment.MEDIA_MOUNTED.equals(state)) { + return false; + } + + File file_thumb; + + try { + file_thumb = File.createTempFile("thumb", null, dir_thumb ); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return false; + } + + String url_thumb = file_thumb.getAbsolutePath(); + + if( !saveBitmapToFileCache(bitmap, file_thumb) ){ + file_thumb.delete(); + return false; + } + + thumbnails.put( position, url_thumb ); + + return true; + } + + private boolean saveBitmapToFileCache(Bitmap bitmap, File file_thumb ) { + + //File fileCacheItem = new File(strFilePath); + OutputStream out = null; + + boolean result = false; + + try + { + //result= fileCacheItem.createNewFile(); + out = new FileOutputStream(file_thumb); + + bitmap.compress(CompressFormat.JPEG, 100, out); + } + catch (Exception e) + { + e.printStackTrace(); + } + finally + { + try + { + out.close(); + result = true; + } + catch (IOException e) + { + e.printStackTrace(); + } + } + + return result; + } /** * A fake Drawable that will be attached to the imageView while the download diff --git a/src/android/Library/src/MultiImageChooserActivity.java b/src/android/Library/src/MultiImageChooserActivity.java index fb16385..278c54f 100644 --- a/src/android/Library/src/MultiImageChooserActivity.java +++ b/src/android/Library/src/MultiImageChooserActivity.java @@ -96,7 +96,10 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi private static final int CURSORLOADER_THUMBS = 0; private static final int CURSORLOADER_REAL = 1; + private Map fileNameGroup = new HashMap(); + private Map fileNames = new HashMap(); + ArrayList thumbFileNames = new ArrayList(); private SparseBooleanArray checkStatus = new SparseBooleanArray(); @@ -109,7 +112,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi private GridView gridView; - private final ImageFetcher fetcher = new ImageFetcher(); + private ImageFetcher fetcher; private int selectedColor = 0xff32b2e1; private boolean shouldRequestThumb = true; @@ -121,6 +124,9 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + + fetcher = new ImageFetcher( getApplicationContext() ); + fakeR = new FakeR(this); setContentView(fakeR.getId("layout", "multiselectorgrid")); fileNames.clear(); @@ -179,12 +185,18 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi @Override public void onItemClick(AdapterView arg0, View view, int position, long id) { - String name = getImageName(position); + + String name = getImageName(position); + String name_thumb = getImageThumbName(position); + int rotation = getImageRotation(position); - if (name == null) { + if (name == null || name_thumb == null ) { return; } + + boolean be_in_group = fileNameGroup.containsKey( position ); + boolean isChecked = !isChecked(position); if (maxImages == 0 && isChecked) { isChecked = false; @@ -199,7 +211,20 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi AlertDialog alert = builder.create(); alert.show(); } else if (isChecked) { + + if( !be_in_group ){ + + FileNameItem fileNameItem = new FileNameItem(); + fileNameItem.original = name; + fileNameItem.thumb = name_thumb; + fileNameItem.rotation = rotation; + + fileNameGroup.put( position, fileNameItem ); + } + fileNames.put(name, new Integer(rotation)); + thumbFileNames.add( name_thumb ); + if (maxImageCount == 1) { this.selectClicked(null); } else { @@ -213,7 +238,13 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi view.setBackgroundColor(selectedColor); } } else { + + if( be_in_group ){ + fileNameGroup.remove(position); + } fileNames.remove(name); + thumbFileNames.remove(name_thumb); + maxImages++; ImageView imageView = (ImageView)view; if (android.os.Build.VERSION.SDK_INT>=16) { @@ -296,12 +327,14 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi getActionBar().getCustomView().findViewById(fakeR.getId("id", "actionbar_done")).setEnabled(false); progress.show(); Intent data = new Intent(); - if (fileNames.isEmpty()) { + /*if (fileNames.isEmpty()) {*/ + if (fileNameGroup.isEmpty()) { this.setResult(RESULT_CANCELED); progress.dismiss(); finish(); } else { - new ResizeImagesTask().execute(fileNames.entrySet()); + /*new ResizeImagesTask().execute(fileNames.entrySet());*/ + new ResizeImagesTask().execute(fileNameGroup.entrySet()); } } @@ -310,9 +343,13 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi * Helper Methods ********************/ private void updateAcceptButton() { + /*((TextView) getActionBar().getCustomView().findViewById(fakeR.getId("id", "actionbar_done_textview"))) + .setEnabled(fileNames.size() != 0);*/ ((TextView) getActionBar().getCustomView().findViewById(fakeR.getId("id", "actionbar_done_textview"))) - .setEnabled(fileNames.size() != 0); - getActionBar().getCustomView().findViewById(fakeR.getId("id", "actionbar_done")).setEnabled(fileNames.size() != 0); + .setEnabled(fileNameGroup.size() != 0); + + /*getActionBar().getCustomView().findViewById(fakeR.getId("id", "actionbar_done")).setEnabled(fileNames.size() != 0);*/ + getActionBar().getCustomView().findViewById(fakeR.getId("id", "actionbar_done")).setEnabled(fileNameGroup.size() != 0); } private void setupHeader() { @@ -371,6 +408,16 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi return name; } + private String getImageThumbName( int position ){ + + imagecursor.moveToPosition(position); + int id = imagecursor.getInt(image_column_index); + + String name = fetcher.getThumbFilePath(id); + + return name; + } + private int getImageRotation(int position) { actualimagecursor.moveToPosition(position); int rotation = 0; @@ -480,20 +527,21 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi } - private class ResizeImagesTask extends AsyncTask>, Void, ArrayList> { + /*private class ResizeImagesTask extends AsyncTask>, Void, ArrayList> {*/ + private class ResizeImagesTask extends AsyncTask>, Void, ArrayList> { private Exception asyncTaskError = null; @Override - protected ArrayList doInBackground(Set>... fileSets) { - Set> fileNames = fileSets[0]; - ArrayList al = new ArrayList(); + protected ArrayList doInBackground(Set>... fileSets) { + Set> fileNames = fileSets[0]; + ArrayList al = new ArrayList(); try { - Iterator> i = fileNames.iterator(); + Iterator> i = fileNames.iterator(); Bitmap bmp; while(i.hasNext()) { - Entry imageInfo = i.next(); - File file = new File(imageInfo.getKey()); - int rotate = imageInfo.getValue().intValue(); + Entry imageInfo = i.next(); + File file = new File(imageInfo.getValue().original); + int rotate = imageInfo.getValue().rotation; BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 1; options.inJustDecodeBounds = true; @@ -538,27 +586,33 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi } file = this.storeImage(bmp, file.getName()); - al.add(Uri.fromFile(file).toString()); + //al.add(Uri.fromFile(file).toString()); + FileNameItem filenameitem = new FileNameItem(); + filenameitem.original = Uri.fromFile(file).toString(); + filenameitem.thumb = imageInfo.getValue().thumb; + filenameitem.rotation = imageInfo.getValue().rotation; + al.add(filenameitem); + fileNameGroup.get( imageInfo.getKey()).original = 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)); + URI uri = new URI(al.get(i).original); File file = new File(uri); file.delete(); } } catch(Exception exception) { // the finally does what we want to do } finally { - return new ArrayList(); + return new ArrayList(); } } } @Override - protected void onPostExecute(ArrayList al) { + protected void onPostExecute(ArrayList al) { Intent data = new Intent(); if (asyncTaskError != null) { @@ -568,7 +622,9 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi setResult(RESULT_CANCELED, data); } else if (al.size() > 0) { Bundle res = new Bundle(); - res.putStringArrayList("MULTIPLEFILENAMES", al); + res.putParcelableArrayList("MULTIPLEFILENAMES", al); + /*res.putStringArrayList("MULTIPLEFILENAMES", al); + res.putStringArrayList("MULTIPLEFILETHUMBNAMES", thumbFileNames );*/ if (imagecursor != null) { res.putInt("TOTALFILES", imagecursor.getCount()); } @@ -617,7 +673,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi int index = fileName.lastIndexOf('.'); String name = fileName.substring(0, index); String ext = fileName.substring(index); - File file = File.createTempFile(name, ext); + File file = File.createTempFile( "_"+name+"_", ext); OutputStream outStream = new FileOutputStream(file); if (ext.compareToIgnoreCase(".png") == 0) { bmp.compress(Bitmap.CompressFormat.PNG, quality, outStream); diff --git a/src/android/com/synconset/ImagePicker/ImagePicker.java b/src/android/com/synconset/ImagePicker/ImagePicker.java index 2f4939a..c2ec866 100644 --- a/src/android/com/synconset/ImagePicker/ImagePicker.java +++ b/src/android/com/synconset/ImagePicker/ImagePicker.java @@ -3,17 +3,24 @@ */ package com.synconset; +import org.apache.commons.io.output.FileWriterWithEncoding; import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaPlugin; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.json.JSONStringer; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; import java.util.ArrayList; +import java.util.HashMap; import android.app.Activity; import android.content.Intent; +import android.os.Bundle; import android.util.Log; public class ImagePicker extends CordovaPlugin { @@ -56,8 +63,47 @@ public class ImagePicker extends CordovaPlugin { 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); + + //HashMap result = new HashMap(); + + //ArrayList fileNames = data.getStringArrayListExtra("MULTIPLEFILENAMES"); + //ArrayList fileThumbNames = data.getStringArrayListExtra("MULTIPLEFILETHUMBNAMES"); + + ArrayList fileNameList = new ArrayList(); + + Bundle bundle = data.getExtras(); + if( bundle != null ){ + fileNameList = bundle.getParcelableArrayList("MULTIPLEFILENAMES"); + } + + Gson gson = new Gson(); + String str_json = gson.toJson(fileNameList); + JSONArray res; + try { + res = new JSONArray(str_json); + } catch (JSONException e) { + // TODO Auto-generated catch block + String error = "error"; + this.callbackContext.error(error); + return; + } + //JsonArray res = gson.toJsonTree(fileNameList).getAsJsonArray(); + + //result.put( "actual", fileNames ); + //result.put("thumb", fileThumbNames ); + + //JSONObject res_object = new JSONObject(result); + //JSONArray res = new JSONArray(fileNameList); + + //JSONArray res = new JSONArray(fileNames); + /*JSONArray res = new JSONArray(); + try { + res = new JSONArray( "[" + res_object.toString() + "]" ); + } catch (JSONException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + }*/ + this.callbackContext.success(res); } else if (resultCode == Activity.RESULT_CANCELED && data != null) { String error = data.getStringExtra("ERRORMESSAGE");