@brunofuster

www.wesaveapp.com

Archive for the ‘iphone’ Category

Wesave, save money and help others save too!

leave a comment »

Hi! I’ve been working hard on my first iphone app for the past year with some friends: Andre Gil, Beck Novaes and Eduardo Horvath.

We hope you enjoy and make use of it! Feel free to send us your feedback at team@wesaveapp.com!

Check it out! Wesave is a really cool app!

www.wesaveapp.com or you can install it right away on the AppStore

Video

Screenshots

Advertisements

Written by brunofuster

October 26, 2011 at 10:09 pm

uploading an image from iphone to appengine blobstore using vraptor

with 8 comments

Its quite simple to do this. I will represent the back-end using vraptor, a really great mvc web framework.

Well, at first, you need to generate the upload URI, provided by GAE’s SDK. When you’re working with web forms, you can just call the BlobstoreService to create the Upload URI directly from your JSP, but this is not the case.

We will provide then a resource that will return an URI for the upload.


@Resource
@Path("/image")
public class ImageController {

    private final BlobstoreSevice blobstoreSevice = BlobstoreServiceFactory.getBlobstoreService();
    private final Result result;

    public ImageController(Result result) {
        this.result = result;
    }

    @Path("/createUploadURI")
    public void uploadURI() {
        
        String uploadURI = blobstoreService.createUploadUrl("/image/upload");
        result.use(http()).body(uploadURI);
    }

}

That’s enough to return the upload URI into the response body (we wont use json or xml at this time to simplify the post).
Just for the record, there’s an issue when running this at development server. Blobstore won’t return the URI with its host, although it will return the absolute URI when at production environment.

Lets consume this resource from iphone now using asihttp.

#import "ASIHTTPRequest.h"
//...

-(void) getUploadURI {

	NSURL *uri = [NSURL URLWithString:@"http://yourserver.appspot.com/image/createUploadURI"]];
	ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:uri];
	[request setDelegate:self];
	[request startAsynchronous];
}

-(void) requestFinished:(ASIHTTPRequest *)request {

	NSString *uri = [request responseData];
}

-(void) requestFailed:(ASIHTTPRequest *)request {
	
	NSError *error = [request error];
	NSLog(@"error %@", error);
}

Now we have the URI to upload an image. Lets create a new objective-c class to handle the upload using asihttp form data (notice that we will also track the upload progress).

#import <Foundation/Foundation.h>
#import "ASIFormDataRequest.h"

@interface ImageUpload : NSObject {

	ASIFormDataRequest *formData;
	float progress;
}

@property (nonatomic, retain) ASIFormDataRequest *formData;
@property (nonatomic, assign) float progress;

-(id) initWithImage:(UIImage*)img uri:(NSString*)uri;
-(void) startUpload;

@end

And it’s implementation:

#import "ImageUpload.h"

@implementation ImageUpload

@synthesize formData, progress;

-(id) initWithImage:(UIImage*)img uri:(NSString*)uri {
	
	NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(img)];

	self.formData = [[ASIFormDataRequest requestWithURL:[NSURL URLWithString:uri]] retain];	
	[self.formData setData:imageData withFileName:@"defaultImage.png" andContentType:@"image/png" forKey:@"defaultImage"];
	[self.formData setDelegate:self];
	[self.formData setUploadProgressDelegate:self];
	
	return self;
}

-(void) startUpload {

	[self.formData startAsynchronous];
}

#pragma mark Upload Progress Tracking

- (void)request:(ASIHTTPRequest *)theRequest didSendBytes:(long long)newLength {
	
	if ([theRequest totalBytesSent] > 0) {
		float progressAmount = (float) ([theRequest totalBytesSent]/[theRequest postLength]);
		self.progress = progressAmount;
	}
	
}

-(void) requestFinished:(ASIHTTPRequest *)request {
	NSLog(@"upload finished");
}

-(void) requestFailed:(ASIHTTPRequest *)request {
	NSError *error = [request error];
	NSLog(@"error %@", error);
}

- (void) dealloc
{
	[self.formData release];
	[super dealloc];
}
@end

Let’s change the requestFinished: method for /image/getUploadURI to start the upload after its response is done.

#import "ImageUpload.h"
//...
-(void) requestFinished:(ASIHTTPRequest *)request {

	ImageUpload *imageUpload = [[ImageUpload alloc] initWithImage:self.imageView.image uri:[request responseData]];
	[imageUpload startUpload];
}

If you want to track the progress at this view, you can create your own delegate like [imageUpload setUploadTrackingProgress:self] or expose the asihttp method setUploadProgressDelegate:.

At last we will create the resource that Blobstore will call on your server after the upload has been completed. You can now use the Images Service to get an URI for this image and store it.

@Path("/upload")
public void upload() {
	Map<String, BlobKey> blobs = blobstoreService.getUploadedBlobs(request);
	BlobKey blob = blobs.get("defaultImage");
		
	ImagesService imagesService = ImagesServiceFactory.getImagesService();
	String imageUrl = imagesService.getServingUrl(blob);

	/* datastore.put(imageurl) */
	result.use(Results.http()).body(imageUrl);
}

We just need to inject the current HttpServletRequest for the BlobstoreService like this:

@Resource
@Path("/image")
public class ImageController {

    private final BlobstoreSevice blobstoreSevice = BlobstoreServiceFactory.getBlobstoreService();
    private final HttpServletRequest request;
    private final Result result;

    public ImageController(Result result, HttpServletRequest request) {
        this.result = result;
        this.request = request;
    }
...

References:
vraptor
asihttp
Blobstore Service
Images Service
http://ikaisays.com/2010/09/08/gwt-blobstore-the-new…

Written by brunofuster

March 11, 2011 at 3:06 pm

restfulie-objectivec simple post, http response codes and basic auth

with one comment

Now restfulie-objectivec is using by default ASIHTTP. Its too coupled by now, but I’m working on this and you will be able to extend it and use any http lib.

You can now call a simple http post method, without a payload. I’m working on the JSON marshaller and it will be ready soon.


Response *response = [[[client at:@"http://localhost:8888/login"] authUser:@"login" andPassword:@"passwd"] post];

if (response.code == 200) {
    NSLog(@"login success");
} else {
    NSLog(@"login fail");
}

Written by brunofuster

January 16, 2011 at 5:45 pm

Restfulie Objective-C startup

leave a comment »

Restfulie-ObjectiveC development has begun. We’re open for ObjC developers who might be interested to collaborate!

By now you can call HTTP Get methods and marshall JSON responses into objects.

For instance, a custom RestClient can be created using Restfulie’s class method customWithTypes:andCollectionNames:


id<RestClient> client = [Restfulie customWithTypes:[NSArray arrayWithObjects:[User class], nil]
                                andCollectionNames:[NSArray arrayWithObjects:@"users", nil]];

Response *response = [[client at:@"http://localhost:8888/users"] get];
NSArray *users = [response resource];

//or a simple user

Response *response = [[client at:@"http://localhost:8888/users/1"] get];
User *user = [response resource];

I’m refactoring the entire project to design it as closer as possible to other Restfulie’s client implementations, so it might change a lot.
If you’d like to collaborate, send me an email: brunofuster@gmail.com

I will keep you posted through this blog explaining the lastest changes and the features that are being implemented at the moment.

https://github.com/caelum/restfulie-objectivec

Written by brunofuster

January 12, 2011 at 12:59 pm

uploading an image from iphone to Amazon S3 with UIImagePicker and ASIHTTP

with one comment

Just organizing and spreading some ideas and tools ;)

Let’s start creating an UIViewController subclass that will attend to UIImagePickerControllerDelegate protocol, so your iphone user can choose an image to upload:

UploadViewController.h


@interface UploadViewController : UIViewController <UIImagePickerControllerDelegate> {

    IBOutlet UIImageView *selectedImage;
    IBOutlet UIButton *selectImageButton;
    IBOutlet UIButton *uploadImageButton;
    UIImagePickerController *imagePicker;
}

@property (nonatomic, retain) IBOutlet UIImageView *selectedImage;
@property (nonatomic, retain) IBOutlet UIButton *selectImageButton;
@property (nonatomic, retain) IBOutlet UIButton *uploadImageButton;
@property (nonatomic, retain) UIImagePickerController *imagePicker;

- (IBAction) showImagePicker:(id) sender;
- (IBAction) uploadImage:(id) sender;
- (void) uploadToAS3Job;

#pragma mark UIImagePickerControllerDelegate methods

- (void) imagePickerController:(UIImagePickerController *) picker
        didFinishPickingImage:(UIImage *) image
        editingInfo:(NSDictionary *) editingInfo;

- (void) imagePickerControllerDidCancel:(UIImagePickerController *) picker;

@end

This view has an ImageView and two buttons: selectImage and uploadImage. You have to create and connect them through IB (except imagePicker) or create them programatically, its your call.

There are also two IBAction methods (showImagePicker and uploadImage). You have to connect their respective buttons using “touch down” event.

Now lets code the implementation:
Ps: Import ASIHTTPRequest into your project.

UploadViewController.m


#import "UploadViewController.h"
#import "ASIS3Request.h"

@implementation UploadViewController

@synthesize selectedImage;
@synthesize selectImageButton;
@synthesize uploadImageButton;
@synthesize imagePicker;

//create UIImagePickerController when this view has loaded

-(void) viewDidLoad {

    self.imagePicker = [[UIImagePickerController alloc] init];
    self.imagePicker.allowsImageEditing = YES;
    self.imagePicker.delegate = self;
    self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}

//show a modal view with the image picker 

-(IBAction) showImagePicker {

    [self presentModalViewController:self.imagePicker animated:YES];
}

#pragma mark UIImagePickerControllerDelegate
//callback method when an image has been selected 

- (void) imagePickerController:(UIImagePickerController *) picker
        didFinishPickingImage:(UIImage *) image
        editingInfo:(NSDictionary *) editingInfo {

    selectedImage.image = image;
    [[picker parentViewController] dismissModalViewControllerAnimated:YES];
}

//callback method when the user cancels the selection

- (void) imagePickerControllerDidCancel:(UIImagePickerController *) picker {

    [[picker parentViewController] dismissModalViewControllerAnimated:YES];
}

//upload image action, will run a task in background 

- (IBAction) uploadImage:(id) sender {

    if (self.selectedImage != nil) {
        [self performSelectorInBackground:@selector(uploadToAS3Job) withObject:nil];
    }
}

//upload in background (just a sample, you should use NSOperationQueue)

- (void) uploadToAS3Job {

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    [ASIS3Request setSharedSecretAccessKey:@"my-secret-access-key"];
    [ASIS3Request setSharedAccessKey:@"my-access-key"];
 
    NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(self.selectedImage)];

    ASIS3ObjectRequest *request = 
            [ASIS3ObjectRequest PUTRequestForData:imageData withBucket:@"bucket" key:@"images/path"];
    [request setShouldCompressRequestBody:YES]; //gzip compression
    [request startSynchronous];

    if ([request error]) {
       NSLog(@"%@",[[request error] localizedDescription]);
    }

    [pool release];

}

- (void) dealloc {

    [imagePicker release];
    [selectedImage release];
    [selectImageButton release];
    [uploadImageButton release];
    [super dealloc];
}

@end

Security issues will be discussed in a new post.

References:
http://www.zimbio.com/iPhone/articles…
http://developer.apple.com/library/…UIImagePickerController.html
http://iphone.zcentric.com/…/using-a-uiimagepickercontroller/
http://iphone.zcentric.com/…/post-a-uiimage-to-the-web/
http://allseeing-i.com/ASIHTTPRequest/S3
http://stackoverflow.com/questions/1754184/amazon-s3-post-upload-from-iphone
http://docs.amazonwebservices.com/AmazonS3/2006-03-01/dev/index.html?UsingHTTPPOST.html
http://stackoverflow.com/questions/1053944/uploading-to-amazon-s3-services-from-iphone-app
http://developer.apple.com/library/ios/…UIImage_Class
http://blog.objectgraph.com/…/download-an-image…
http://developer.apple.com/library/mac/…NSData_Class

Written by brunofuster

November 3, 2010 at 3:04 pm