Hi Guys
In today’s world, people don’t want to do any manual work they want to do smart work and at the same time they don’t want store there data on the physical drive, the world is so much involved to use the technology to store their data in the cloud by which people can access their data whenever and wherever they want. Its also requires some time to implement the functionality to store their data on google drive through the iOS app. To access the user’s google drive we have to link their Gmail account with the iOS app. Here are the steps that you should follow to implement the google drive in iOS with swift.
Step:1=> Add following pods into your pod file
=> Open the terminal and migrate to Xcode project
=> If you don’t have a podfile into your Xcode project the run “pod init” command
=> Now run the command “open podfile” and then add the following pods into your podfile.
1 2 3 4 5 |
<span class="pln">platform </span><span class="pun">:</span><span class="pln">ios</span><span class="pun">,</span> <span class="str">'8.0'</span><span class="pln"> target </span><span class="str">'QuickstartApp'</span> <span class="kwd">do</span><span class="pln"> pod </span><span class="str">'GoogleAPIClientForREST/Sheets'</span><span class="pun">,</span> <span class="str">'~> 1.2.1'</span><span class="pln"> pod </span><span class="str">'GoogleSignIn'</span><span class="pun">,</span> <span class="str">'~> 4.1.1'</span><span class="pln"> end</span> |
=> After this, save your pod file and run the command “pod install”.
Steps:2=> Enable the Google sign in functionality to the AppDelegate class.
To enable sign in, you must configure the shared GoogleSignIn instance to your app. Implement this instance wherever you can, but according to me, we should register it at a time of opening the app. Add the following code in App Delegate class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import GoogleSignIn func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { GIDSignIn.sharedInstance().clientID = "YOUR_CLIENT_ID" GIDSignIn.sharedInstance().delegate = self return true } func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool { return GIDSignIn.sharedInstance().handle((url as URL??)!, sourceApplication: sourceApplication, annotation: annotation) } func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject?) -> Bool { var options: [String: AnyObject] = [UIApplicationOpenURLOptionsKey.sourceApplication.rawValue: sourceApplication as AnyObject, UIApplicationOpenURLOptionsKey.annotation.rawValue: annotation!] return GIDSignIn.sharedInstance().handle((url as URL??)!, sourceApplication: sourceApplication, annotation: annotation) } |
Step3=> Implement the Google Sign before using the drive.
=> Import GoogleSignIn in your controller.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
import GoogleSignIn class controllerName: UIViewController , GIDSignInUIDelegate{ let driveService = GTLRDriveService() override func viewDidLoad() { super.viewDidLoad() setupGoogleSignIn() } private func setupGoogleSignIn(){ GIDSignIn.sharedInstance().delegate = self GIDSignIn.sharedInstance().uiDelegate = self GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDriveFile] GIDSignIn.sharedInstance().signInSilently() } } extension SettingViewController: GIDSignInDelegate { func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) { if let _ = error { driveService.authorizer = nil } else { driveService.authorizer = user.authentication.fetcherAuthorizer() // self.click_retriveButtonFromDrive(self) } } } |
In above code sign method is a delegate which ensures that the user has signed with there Gmail account or not. If not then it shows the Gmail default popup to sign in from your Gmail account first with the app.
Step4=> To store the app data on google drive , first we make a custom file which contain our data that we will upload on the drive. Before sending the content to drive we first save the data to the file in the JSON format. So when retrieving we can parse it easily.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
//Class which create file. Call this methos with that content and import Foundation class FileHandler{ init() { } func openfile(fileContentToWrite : String){ let fileName = "File Name.txt" var filePath = "" let dirs : [String] = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.allDomainsMask, true) if dirs.count > 0 { let dir = dirs[0] //documents directory filePath = dir.appending("/" + fileName) FGSingleton.sharedInstance.filePath = filePath print("Local path = \(filePath)") } else { print("Could not find local directory to store file") return } // let fileContentToWrite = "Text to be recorded into file" do { try <span style="color: #333333">fileContentToWrite.write(toFile:</span> filePath, atomically: false, encoding: String.Encoding.utf8) print("SuccesfullyUpdate into File") } catch let error as NSError { print("An error took place: \(error)") } } } |
After successfully saving the data on the file you are almost ready to upload the content on the drive.
Steps5=> Instead of writing all the code on the same class I make a seperate class which explained all the method for google drive , By that we can use it easily and it make a code more readable. Class Contain the search , upload file ,delete and download method respectively.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
import Foundation import GoogleAPIClientForREST enum GDriveError: Error { case NoDataAtPath } class GoogleDrive { private let service: GTLRDriveService init(_ service: GTLRDriveService) { self.service = service } public func uploadFile(_ folderName: String, filePath: String, MIMEType: String, onCompleted: ((String?, Error?) -> ())?) { search(folderName) { (folderID, error) in if let ID = folderID { self.upload(ID, path: filePath, MIMEType: MIMEType, onCompleted: onCompleted) } else { self.createFolder(folderName, onCompleted: { (folderID, error) in guard let ID = folderID else { onCompleted?(nil, error) return } self.upload(ID, path: filePath, MIMEType: MIMEType, onCompleted: onCompleted) }) } } } private func upload(_ parentID: String, path: String, MIMEType: String, onCompleted: ((String?, Error?) -> ())?) { guard let data = FileManager.default.contents(atPath: path) else { onCompleted?(nil, GDriveError.NoDataAtPath) return } let file = GTLRDrive_File() file.name = path.components(separatedBy: "/").last file.parents = [parentID] let uploadParams = GTLRUploadParameters.init(data: data, mimeType: MIMEType) uploadParams.shouldUploadWithSingleRequest = true let query = GTLRDriveQuery_FilesCreate.query(withObject: file, uploadParameters: uploadParams) query.fields = "id" self.service.executeQuery(query, completionHandler: { (ticket, file, error) in onCompleted?((file as? GTLRDrive_File)?.identifier, error) }) } public func download(_ fileID: String, onCompleted: @escaping (Data?, Error?) -> ()) { let query = GTLRDriveQuery_FilesGet.queryForMedia(withFileId: fileID) service.executeQuery(query) { (ticket, file, error) in print("Ticket\(ticket)") print("FILE \(file.debugDescription)") onCompleted((file as? GTLRDataObject)?.data, error) } } public func search(_ fileName: String, onCompleted: @escaping (String?, Error?) -> ()) { let query = GTLRDriveQuery_FilesList.query() query.pageSize = 1 query.q = "name contains '\(fileName)'" service.executeQuery(query) { (ticket, results, error) in onCompleted((results as? GTLRDrive_FileList)?.files?.first?.identifier, error) } } public func createFolder(_ name: String, onCompleted: @escaping (String?, Error?) -> ()) { let file = GTLRDrive_File() file.name = name file.mimeType = "application/vnd.google-apps.folder" let query = GTLRDriveQuery_FilesCreate.query(withObject: file, uploadParameters: nil) query.fields = "id" service.executeQuery(query) { (ticket, folder, error) in onCompleted((folder as? GTLRDrive_File)?.identifier, error) } } public func delete(_ fileID: String, onCompleted: ((Error?) -> ())?) { let query = GTLRDriveQuery_FilesDelete.query(withFileId: fileID) service.executeQuery(query) { (ticket, nilFile, error) in onCompleted?(error) } } } |
Steps6=> Now you are on the coast to complete this task. Last Step?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
import UIKit import GoogleSignIn import GTMOAuth2 import GoogleAPIClientForREST import GTMSessionFetcher import GoogleAPIClientForREST import SystemConfiguration import LocalAuthentication class controllerName: UIViewController , GIDSignInUIDelegate{ @IBOutlet weak var auth_View: UIView! let appDelegate = UIApplication.shared.delegate as! AppDelegate let driveService = GTLRDriveService() private var drive: GoogleDrive? var openFile : FileHandler! override func viewDidLoad() { super.viewDidLoad() setupGoogleSignIn() drive = GoogleDrive(driveService) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } //MARK:- Actions @IBAction func click_BackupData(_ sender: Any) { if FGSingleton.sharedInstance.connection{ DispatchQueue.main.async { Indicator.shared.showProgressView(self.view) self.drive?.search("fileName.txt", onCompleted: { (fileID, error) in if fileID != nil { self.drive?.delete(fileID!, onCompleted: {(Error) in print("Deleted Old File") }) }else{ } }) guard let arrayCount : Int = self.appDelegate.db.executeQueryForSelect(category: "").count , arrayCount != 0 else { Indicator.shared.hideProgressView() return } self.openFile = FileHandler.init() self.openFile.openfile(fileContentToWrite: json(from: createDataToInsertIntoFile(storyArray: self.appDelegate.db.executeQueryForSelect(category: "")))! ) self.drive?.uploadFile("Name", filePath: FGSingleton.sharedInstance.filePath , MIMEType: "text/plain", onCompleted: { (fileID, error) in if fileID != nil { Indicator.shared.hideProgressView() }else{ Indicator.shared.hideProgressView() GIDSignIn.sharedInstance().signIn() } }) } }else{ } } @IBAction func click_retriveButtonFromDrive(_ sender: Any) { Indicator.shared.showProgressView(self.view) drive?.search("rudra_Diary.txt", onCompleted: { (fileID, error) in if fileID != nil { self.retrivedData (fileID : fileID!) }else{ Indicator.shared.hideProgressView() GIDSignIn.sharedInstance().signIn() } }) Indicator.shared.hideProgressView() } func retrivedData (fileID : String){ Indicator.shared.showProgressView(self.view) print(fileID) drive?.download(fileID, onCompleted: { (data, error) in let webString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue) print((webString!)) let str = webString! as String print(String(describing: str)) let data = str.data(using: String.Encoding.utf8)! do { let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) print("Jsonn \(json)") if let jsonResult = json as? Array<Any>{ if self.appDelegate.db.executeQueryForSelect(category: "").count == jsonResult.count{ Indicator.shared.hideProgressView() }else{ for i in 0...jsonResult.count - 1{ self.appDelegate.db.insertDatIntoTable(storyName: (jsonResult[i]as! NSDictionary).value(forKey: "Title")as! NSString, Text: (jsonResult[i]as! NSDictionary).value(forKey: "Text")as! NSString, category: (jsonResult[i]as! NSDictionary).value(forKey: "Category")as! NSString, Date: (jsonResult[i]as! NSDictionary).value(forKey: "Date")as! NSString, Image: (jsonResult[i]as! NSDictionary).value(forKey: "Image")as! NSString) } Indicator.shared.hideProgressView() } }else if json is NSMutableDictionary{ } }catch{ print(error) } }) } private func setupGoogleSignIn(){ GIDSignIn.sharedInstance().delegate = self GIDSignIn.sharedInstance().uiDelegate = self GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDriveFile] GIDSignIn.sharedInstance().signInSilently() } } extension SettingViewController: GIDSignInDelegate { func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) { if let _ = error { driveService.authorizer = nil } else { driveService.authorizer = user.authentication.fetcherAuthorizer() // self.click_retriveButtonFromDrive(self) } } } |
Hurray, You have successfully implemented the Google Drive to your app. If you have any queries, then please ask in the comment.
Thank you, Good Day ?
Recent Comments