Google Drive integration in Native iOS

Posted By : Ashish Tyagi | 03-Dec-2013

Google drive is widely used for creating and storing document file.We are going to create a iOS app by using Google Drive API which authorize user to upload/save a image in their gmail account.

Let Start to Integrate Google drive in iOS App

1.) Firstly ,You have to register your app here

2.) Create a new project with native (Do not choose iOS as the installed application type. Select Native.)

3.)In left sidebar, select APIs & auth. In the displayed list of APIs and set Drive API status to ON.

4.) select Registered apps option and select your app . to Find Client iD and Client Secret key ,click on “Download Json” .Then a json file is download

On opening this file ,You will get all credentials which are required to connect your app with Google Drive

5.) Now ,open your terminal and go to your project folder ,then Run the following command for installing “Google Client Library”.

svn checkout http://google-api-objectivec-client.googlecode.com/svn/trunk/ google-api-objectivec-client-read-only
        

6.) Create a new project for the app using the Single View Application template and open google-api-objectivec-client-read-only/Source folder and Drag and drop GTL.xcodeproj in your project navigator.

7.) Expend "Link Binary with Libraries" list by selcting Build Setting of your project. and following Framework ::

libGTLTouchStaticLib.a ,Security.framework ,SystemConfiguration.framework and MobileCoreServices.framework

8.) Open Other linker flag in xcode and add -ObjC , -all_load as shown bellow

9.) Open Project's Build Settings and Type User Header Search Path in Search box . and then add path for Source folder of google-api-objectivec-client-read-only

For Example

:/Users/oodles/Documents/GDriveDemo/GDriveDemo/google-api-objectivec-client-read-only/Source

10.) Expend GTL Source/Common/OAuth2/Touch folder in GTLxcodeproj and Drag GTMOAuth2ViewTouch.xib from here to main project supporting folder

11.) In Finder, Drag and Drop GTLDrive.h and GTLDrive_Sources.m from the Source/Services/Drive/Generated to your project

12.) Now ,Open your viewController.h file and Replace your code as given bellow ::

#import <UIKit/UIKit.h>
#import <MobileCoreServices/MobileCoreServices.h>

#import "GTMOAuth2ViewControllerTouch.h"
#import "GTLDrive.h"

@interface ViewController : UIViewController 

@property (nonatomic, retain) GTLServiceDrive *driveService;

@end


13.) Again Open ViewController.m File and Replace your code as given Bellow ::

#import "ViewController.h"

static NSString *const kKeychainItemName = @"YOUR PROJECT NAME";
static NSString *const kClientID = @"YOUR_CLIENT_ID";
static NSString *const kClientSecret = @"YOUR_CLIENT_SECRET";

@implementation ViewController

@synthesize driveService;

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Initialize the drive service & load existing credentials from the keychain if available
    self.driveService = [[GTLServiceDrive alloc] init];
    self.driveService.authorizer = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
                                                                                         clientID:kClientID
                                                                                     clientSecret:kClientSecret];
}

- (void)viewDidAppear:(BOOL)animated
{
    // Always display the camera UI.
    [self showCamera];
}

- (void)showCamera
{
    UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])
    {
        cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
    }
    else
    {
        // In case we're running the iPhone simulator, fall back on the photo library instead.
        cameraUI.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
        if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
        {
            [self showAlert:@"Error" message:@"Sorry, iPad Simulator not supported!"];
            return;
        }
    };
    cameraUI.mediaTypes = [[NSArray alloc] initWithObjects: (NSString *) kUTTypeImage, nil];
    cameraUI.allowsEditing = YES;
    cameraUI.delegate = self;
    [self presentModalViewController:cameraUI animated:YES];

    if (![self isAuthorized])
    {
        // Not yet authorized, request authorization and push the login UI onto the navigation stack.
        [cameraUI pushViewController:[self createAuthController] animated:YES];
    }
}

// Handle selection of an image
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage];
    [self dismissModalViewControllerAnimated:YES];
    [self uploadPhoto:image];
}

// Handle cancel from image picker/camera.
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [self dismissModalViewControllerAnimated:YES];
}

// Helper to check if user is authorized
- (BOOL)isAuthorized
{
    return [((GTMOAuth2Authentication *)self.driveService.authorizer) canAuthorize];
}

// Creates the auth controller for authorizing access to Google Drive.
- (GTMOAuth2ViewControllerTouch *)createAuthController
{
    GTMOAuth2ViewControllerTouch *authController;
    authController = [[GTMOAuth2ViewControllerTouch alloc] initWithScope:kGTLAuthScopeDriveFile
                                                                clientID:kClientID
                                                            clientSecret:kClientSecret
                                                        keychainItemName:kKeychainItemName
                                                                delegate:self
                                                        finishedSelector:@selector(viewController:finishedWithAuth:error:)];
    return authController;
}

// Handle completion of the authorization process, and updates the Drive service
// with the new credentials.
- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController
      finishedWithAuth:(GTMOAuth2Authentication *)authResult
                 error:(NSError *)error
{
    if (error != nil)
    {
        [self showAlert:@"Authentication Error" message:error.localizedDescription];
        self.driveService.authorizer = nil;
    }
    else
    {
        self.driveService.authorizer = authResult;
    }
}

// Uploads a photo to Google Drive
- (void)uploadPhoto:(UIImage*)image
{
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"'Quickstart Uploaded File ('EEEE MMMM d, YYYY h:mm a, zzz')"];

    GTLDriveFile *file = [GTLDriveFile object];
    file.title = [dateFormat stringFromDate:[NSDate date]];
    file.descriptionProperty = @"Uploaded from the Google Drive iOS Quickstart";
    file.mimeType = @"image/png";

    NSData *data = UIImagePNGRepresentation((UIImage *)image);
    GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithData:data MIMEType:file.mimeType];
    GTLQueryDrive *query = [GTLQueryDrive queryForFilesInsertWithObject:file
                                                       uploadParameters:uploadParameters];

    UIAlertView *waitIndicator = [self showWaitIndicator:@"Uploading to Google Drive"];

    [self.driveService executeQuery:query
        completionHandler:^(GTLServiceTicket *ticket,
                            GTLDriveFile *insertedFile, NSError *error) {
            [waitIndicator dismissWithClickedButtonIndex:0 animated:YES];
            if (error == nil)
            {
                NSLog(@"File ID: %@", insertedFile.identifier);
                [self showAlert:@"Google Drive" message:@"File saved!"];
            }
            else
            {
                NSLog(@"An error occurred: %@", error);
                [self showAlert:@"Google Drive" message:@"Sorry, an error occurred!"];
            }
        }];
}

// Helper for showing a wait indicator in a popup
- (UIAlertView*)showWaitIndicator:(NSString *)title
{
    UIAlertView *progressAlert;
    progressAlert = [[UIAlertView alloc] initWithTitle:title
                                               message:@"Please wait..."
                                              delegate:nil
                                     cancelButtonTitle:nil
                                     otherButtonTitles:nil];
    [progressAlert show];

    UIActivityIndicatorView *activityView;
    activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    activityView.center = CGPointMake(progressAlert.bounds.size.width / 2,
                                      progressAlert.bounds.size.height - 45);

    [progressAlert addSubview:activityView];
    [activityView startAnimating];
    return progressAlert;
}

// Helper for showing an alert
- (void)showAlert:(NSString *)title message:(NSString *)message
{
    UIAlertView *alert;
    alert = [[UIAlertView alloc] initWithTitle: title
                                               message: message
                                              delegate: nil
                                     cancelButtonTitle: @"OK"
                                     otherButtonTitles: nil];
    [alert show];
}
@end

        

14.) Run your app and if you getting a error related to redirect url then Create a new Client id for native application as shown bellow and run again with new client id and Client secret key.When your app run properly on real Device then Your device camera is open for taking a image otherwise you can also select a image from photo gallery and then upload this image to google drive.

If you want to know more about Google Drive then Search for Google Drive SDK or See this video tutorial by click here and Download the Sample Code

Hope it is useful for you :)

Aashish Tyagi

[email protected]

About Author

Author Image
Ashish Tyagi

Ashish is a iPhone application developer with experience in Objective-C , Titanium and Phonegap frameworks. Ashish loves watching movies in his free time.

Request for Proposal

Name is required

Comment is required

Sending message..