#2 Support for iCloud photos on iOS - modifications

This commit is contained in:
EddyVerbruggen
2015-10-29 22:04:55 +01:00
parent b88f7107f7
commit 3900d47c4e
7 changed files with 245 additions and 157 deletions
@@ -64,7 +64,6 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Base64;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.Display;
import android.view.LayoutInflater;
@@ -105,7 +104,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
private int maxImages;
private int maxImageCount;
private int desiredWidth;
private int desiredHeight;
private int quality;
@@ -117,9 +116,9 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
private int selectedColor = 0xff32b2e1;
private boolean shouldRequestThumb = true;
private FakeR fakeR;
private ProgressDialog progress;
@Override
@@ -138,7 +137,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
colWidth = width / 4;
gridView = (GridView) findViewById(fakeR.getId("id", "gridview"));
@@ -181,7 +180,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
progress.setTitle("Processing Images");
progress.setMessage("This may take a few moments");
}
@Override
public void onItemClick(AdapterView<?> arg0, View view, int position, long id) {
String name = getImageName(position);
@@ -197,7 +196,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
builder.setTitle("Maximum " + maxImageCount + " Photos");
builder.setMessage("You can only select " + maxImageCount + " photos at a time.");
builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
@@ -290,7 +289,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
actualimagecursor = null;
}
}
public void cancelClicked(View ignored) {
setResult(RESULT_CANCELED);
finish();
@@ -309,8 +308,8 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
new ResizeImagesTask().execute(fileNames.entrySet());
}
}
/*********************
* Helper Methods
********************/
@@ -375,7 +374,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
}
return name;
}
private int getImageRotation(int position) {
actualimagecursor.moveToPosition(position);
int rotation = 0;
@@ -387,13 +386,13 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
}
return rotation;
}
public boolean isChecked(int position) {
boolean ret = checkStatus.get(position);
return ret;
}
/*********************
* Nested Classes
********************/
@@ -407,8 +406,8 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
}
}
private class ImageAdapter extends BaseAdapter {
private final Bitmap mPlaceHolderBitmap;
@@ -465,14 +464,14 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
if (android.os.Build.VERSION.SDK_INT>=16) {
imageView.setImageAlpha(128);
} else {
imageView.setAlpha(128);
imageView.setAlpha(128);
}
imageView.setBackgroundColor(selectedColor);
} else {
if (android.os.Build.VERSION.SDK_INT>=16) {
imageView.setImageAlpha(255);
} else {
imageView.setAlpha(255);
imageView.setAlpha(255);
}
imageView.setBackgroundColor(Color.TRANSPARENT);
}
@@ -483,8 +482,8 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
return imageView;
}
}
private class ResizeImagesTask extends AsyncTask<Set<Entry<String, Integer>>, Void, ArrayList<String>> {
private Exception asyncTaskError = null;
@@ -544,7 +543,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
if(outputType == OutputType.FILE_URI) {
file = this.storeImage(bmp, file.getName());
al.add(Uri.fromFile(file).toString());
al.add(Uri.fromFile(file).toString());
} else if (outputType == OutputType.BASE64_STRING){
al.add(getBase64OfImage(bmp));
}
@@ -558,14 +557,12 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
File file = new File(uri);
file.delete();
}
} catch(Exception exception) {
// the finally does what we want to do
} finally {
return new ArrayList<String>();
} catch(Exception ignore) {
}
return new ArrayList<String>();
}
}
@Override
protected void onPostExecute(ArrayList<String> al) {
Intent data = new Intent();
@@ -612,11 +609,11 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
}
return bmp;
}
/*
* The following functions are originally from
* https://github.com/raananw/PhoneGap-Image-Resizer
*
*
* They have been modified by Andrew Stephan for Sync OnSet
*
* The software is open source, MIT Licensed.
@@ -637,7 +634,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
outStream.close();
return file;
}
private Bitmap getResizedBitmap(Bitmap bm, float factor) {
int width = bm.getWidth();
int height = bm.getHeight();
@@ -646,35 +643,34 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
// resize the bit map
matrix.postScale(factor, factor);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
return Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
}
private String getBase64OfImage(Bitmap bm) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
return Base64.encodeToString(byteArray, Base64.DEFAULT);
}
}
private int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
@@ -682,7 +678,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
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;
float heightScale = 1.0f;
@@ -706,7 +702,7 @@ public class MultiImageChooserActivity extends Activity implements OnItemClickLi
}
}
}
return scale;
}
+1 -1
View File
@@ -140,7 +140,7 @@ static UIColor *disabledColor;
_fetch.textColor = titleColor;
_fetch.textAlignment = NSTextAlignmentCenter;
_fetch.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
_fetch.text = @"fetching";
_fetch.text = @""; // removed 'fetching'
[self addSubview:_fetch];
}
+2 -1
View File
@@ -403,7 +403,8 @@ NSString * const GMGridViewCellIdentifier = @"GMGridViewCellIdentifier";
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
fetch_item.be_saving_img_thumb = false;
// TODO pass in quality
if ( ![ UIImageJPEGRepresentation(result, 1.0f ) writeToFile:filePath atomically:YES ] ) {
return;
}
+141 -102
View File
@@ -7,9 +7,10 @@
//
#import "SOSPicker.h"
#import "ELCAlbumPickerController.h"
#import "ELCImagePickerController.h"
#import "ELCAssetTablePicker.h"
#import "GMImagePickerController.h"
#import "GMFetchItem.h"
#define CDV_PHOTO_PREFIX @"cdv_photo_"
@@ -18,114 +19,51 @@ typedef enum : NSUInteger {
BASE64_STRING = 1
} SOSPickerOutputType;
@implementation SOSPicker
@interface SOSPicker () <GMImagePickerControllerDelegate>
@end
@implementation SOSPicker
@synthesize callbackId;
- (void) getPictures:(CDVInvokedUrlCommand *)command {
NSDictionary *options = [command.arguments objectAtIndex: 0];
NSInteger maximumImagesCount = [[options objectForKey:@"maximumImagesCount"] integerValue];
self.width = [[options objectForKey:@"width"] integerValue];
self.height = [[options objectForKey:@"height"] integerValue];
self.quality = [[options objectForKey:@"quality"] integerValue];
NSDictionary *options = [command.arguments objectAtIndex: 0];
self.outputType = [[options objectForKey:@"outputType"] integerValue];
BOOL allow_video = [[options objectForKey:@"allow_video" ] boolValue ];
NSString * title = [options objectForKey:@"title"];
NSString * message = [options objectForKey:@"message"];
if (message == (id)[NSNull null]) {
message = nil;
}
self.width = [[options objectForKey:@"width"] integerValue];
self.height = [[options objectForKey:@"height"] integerValue];
self.quality = [[options objectForKey:@"quality"] integerValue];
// Create the an album controller and image picker
ELCAlbumPickerController *albumController = [[ELCAlbumPickerController alloc] init];
if (maximumImagesCount == 1) {
albumController.immediateReturn = true;
albumController.singleSelection = true;
} else {
albumController.immediateReturn = false;
albumController.singleSelection = false;
}
ELCImagePickerController *imagePicker = [[ELCImagePickerController alloc] initWithRootViewController:albumController];
imagePicker.maximumImagesCount = maximumImagesCount;
imagePicker.returnsOriginalImage = 1;
imagePicker.imagePickerDelegate = self;
albumController.parent = imagePicker;
self.callbackId = command.callbackId;
// Present modally
[self.viewController presentViewController:imagePicker
animated:YES
completion:nil];
self.callbackId = command.callbackId;
[self launchGMImagePicker:allow_video title:title message:message];
}
- (void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info {
CDVPluginResult* result = nil;
NSMutableArray *resultStrings = [[NSMutableArray alloc] init];
NSData* data = nil;
NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
NSError* err = nil;
NSFileManager* fileMgr = [[NSFileManager alloc] init];
NSString* filePath;
ALAsset* asset = nil;
UIImageOrientation orientation = UIImageOrientationUp;;
CGSize targetSize = CGSizeMake(self.width, self.height);
for (NSDictionary *dict in info) {
asset = [dict objectForKey:@"ALAsset"];
// From ELCImagePickerController.m
int i = 1;
do {
filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_PHOTO_PREFIX, i++, @"jpg"];
} while ([fileMgr fileExistsAtPath:filePath]);
@autoreleasepool {
ALAssetRepresentation *assetRep = [asset defaultRepresentation];
CGImageRef imgRef = NULL;
//defaultRepresentation returns image as it appears in photo picker, rotated and sized,
//so use UIImageOrientationUp when creating our image below.
if (picker.returnsOriginalImage) {
imgRef = [assetRep fullResolutionImage];
orientation = [assetRep orientation];
} else {
imgRef = [assetRep fullScreenImage];
}
UIImage* image = [UIImage imageWithCGImage:imgRef scale:1.0f orientation:orientation];
if (self.width == 0 && self.height == 0) {
data = UIImageJPEGRepresentation(image, self.quality/100.0f);
} else {
UIImage* scaledImage = [self imageByScalingNotCroppingForSize:image toSize:targetSize];
data = UIImageJPEGRepresentation(scaledImage, self.quality/100.0f);
}
if (![data writeToFile:filePath options:NSAtomicWrite error:&err]) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
break;
} else {
if(self.outputType == BASE64_STRING){
[resultStrings addObject:[data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]];
} else {
[resultStrings addObject:[[NSURL fileURLWithPath:filePath] absoluteString]];
}
}
}
}
if (nil == result) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:resultStrings];
}
[self.viewController dismissViewControllerAnimated:YES completion:nil];
[self.commandDelegate sendPluginResult:result callbackId:self.callbackId];
- (void)launchGMImagePicker:(bool)allow_video title:(NSString *)title message:(NSString *)message
{
GMImagePickerController *picker = [[GMImagePickerController alloc] init:allow_video];
picker.delegate = self;
picker.title = title;
picker.customNavigationBarPrompt = message;
picker.colsInPortrait = 4;
picker.colsInLandscape = 6;
picker.minimumInteritemSpacing = 2.0;
picker.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *popPC = picker.popoverPresentationController;
popPC.permittedArrowDirections = UIPopoverArrowDirectionAny;
popPC.sourceView = picker.view;
//popPC.sourceRect = nil;
[self.viewController showViewController:picker sender:nil];
}
- (void)elcImagePickerControllerDidCancel:(ELCImagePickerController *)picker {
[self.viewController dismissViewControllerAnimated:YES completion:nil];
CDVPluginResult* pluginResult = nil;
NSArray* emptyArray = [NSArray array];
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:emptyArray];
[self.commandDelegate sendPluginResult:pluginResult callbackId:self.callbackId];
}
- (UIImage*)imageByScalingNotCroppingForSize:(UIImage*)anImage toSize:(CGSize)frameSize
{
@@ -170,4 +108,105 @@ typedef enum : NSUInteger {
return newImage;
}
@end
#pragma mark - UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker.presentingViewController dismissViewControllerAnimated:YES completion:nil];
NSLog(@"UIImagePickerController: User finished picking assets");
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker.presentingViewController dismissViewControllerAnimated:YES completion:nil];
NSLog(@"UIImagePickerController: User pressed cancel button");
}
#pragma mark - GMImagePickerControllerDelegate
- (void)assetsPickerController:(GMImagePickerController *)picker didFinishPickingAssets:(NSArray *)fetchArray
{
[picker.presentingViewController dismissViewControllerAnimated:YES completion:nil];
NSLog(@"GMImagePicker: User finished picking assets. Number of selected items is: %lu", (unsigned long)fetchArray.count);
NSMutableArray * result_all = [[NSMutableArray alloc] init];
CGSize targetSize = CGSizeMake(self.width, self.height);
NSFileManager* fileMgr = [[NSFileManager alloc] init];
NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
NSError* err = nil;
int i = 1;
NSString* filePath;
CDVPluginResult* result = nil;
for (GMFetchItem *item in fetchArray) {
if ( !item.image_fullsize ) {
continue;
}
do {
filePath = [NSString stringWithFormat:@"%@/%@%03d.%@", docsPath, CDV_PHOTO_PREFIX, i++, @"jpg"];
} while ([fileMgr fileExistsAtPath:filePath]);
NSData* data = nil;
if (self.width == 0 && self.height == 0) {
// no scaling required
if (self.outputType == BASE64_STRING){
UIImage* image = [UIImage imageNamed:item.image_fullsize];
[result_all addObject:[UIImageJPEGRepresentation(image, self.quality/100.0f) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]];
} else {
if (self.quality == 100) {
// no scaling, no downsampling, this is the fastest option
[result_all addObject:item.image_fullsize];
} else {
// resample first
UIImage* image = [UIImage imageNamed:item.image_fullsize];
data = UIImageJPEGRepresentation(image, self.quality/100.0f);
if (![data writeToFile:filePath options:NSAtomicWrite error:&err]) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
break;
} else {
[result_all addObject:[[NSURL fileURLWithPath:filePath] absoluteString]];
}
}
}
} else {
// scale
UIImage* image = [UIImage imageNamed:item.image_fullsize];
UIImage* scaledImage = [self imageByScalingNotCroppingForSize:image toSize:targetSize];
data = UIImageJPEGRepresentation(scaledImage, self.quality/100.0f);
if (![data writeToFile:filePath options:NSAtomicWrite error:&err]) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[err localizedDescription]];
break;
} else {
if(self.outputType == BASE64_STRING){
[result_all addObject:[data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]];
} else {
[result_all addObject:[[NSURL fileURLWithPath:filePath] absoluteString]];
}
}
}
}
if (result == nil) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:result_all];
}
[self.viewController dismissViewControllerAnimated:YES completion:nil];
[self.commandDelegate sendPluginResult:result callbackId:self.callbackId];
}
//Optional implementation:
-(void)assetsPickerControllerDidCancel:(GMImagePickerController *)picker
{
NSLog(@"GMImagePicker: User pressed cancel button");
}
@end