Zhou Haibo
Zhou Haibo

Reputation: 2078

How to list files and folder in Google drive root folder

This code is used to show google drive contents in my iOS app. Now I could sign in and show contents by using below query "mimeType ='\(mimeType)' or mimeType = 'application/vnd.google-apps.folder'".

The problem is that it returns all the mp3 files even the ones inside sub-folders, that is not what I want. I want to show the same structure as google drive root. Then when a user enter any sub-folder, I would send another request to retrieve the mp3 files in that sub-folder.

So how could I reconstruct this query to achieve it?

// the code to filter/search google drive files.

import Foundation
import GoogleAPIClientForREST

class GoogleDriveAPI {
    private let service: GTLRDriveService
    
    init(service: GTLRDriveService) {
        self.service = service
    }
    
    public func search(_ mimeType: String, onCompleted: @escaping ([GTLRDrive_File]?, Error?) -> ()) {
        let query = GTLRDriveQuery_FilesList.query()
        query.pageSize = 100
        query.q = "mimeType ='\(mimeType)' or mimeType = 'application/vnd.google-apps.folder'"
        self.service.executeQuery(query) { (ticket, results, error) in
            onCompleted((results as? GTLRDrive_FileList)?.files, error)
        }
    }

Upvotes: 1

Views: 1243

Answers (2)

Zhou Haibo
Zhou Haibo

Reputation: 2078

Per DalmTo's answer, I have changed my code and have some test. Now I get what I want.

In short, I split the list file into two steps, first to search with query = 'root' in parents", which will list all contents in root folder. Then I do a filter files?.filter { $0.mimeType == "audio/mpeg" || $0.mimeType == "application/vnd.google-apps.folder"} before passing that data source to another ViewController.

To do this, I get every folders in root and every mp3 files in root, other type of files are ignored. Then if a user enter one folder in root, I would do another http request(file list) to get its content.

Google drive API function.
import Foundation
import GoogleAPIClientForREST

class GoogleDriveAPI {
    private let service: GTLRDriveService
    
    init(service: GTLRDriveService) {
        self.service = service
    }
    
    public func search(onCompleted: @escaping ([GTLRDrive_File]?, Error?) -> ()) {
        let query = GTLRDriveQuery_FilesList.query()
        query.pageSize = 100
        // query.q = "mimeType ='\(mimeType)' or mimeType = 'application/vnd.google-apps.folder'"
        query.q = "'root' in parents"
        self.service.executeQuery(query) { (ticket, results, error) in
            onCompleted((results as? GTLRDrive_FileList)?.files, error)
        }
    }

call api from a ViewController, and I put a bit context here to make it clear.

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .gray
        
        setViews()
        
        // add an observer on notification "userDidSignInGoogle"
        NotificationCenter.default.addObserver(self, selector: #selector(userDidSignInGoogle), name: .signInGoogleCompleted, object: nil)
        
        setUpGoogleSignIn()
    }
    
    func setUpGoogleSignIn() {
        GIDSignIn.sharedInstance().delegate = self
        GIDSignIn.sharedInstance().uiDelegate = self
        GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDrive]
        GIDSignIn.sharedInstance().signInSilently()
    }
    
    // MARK: - Notification
    @objc private func userDidSignInGoogle(_ notification: Notification) {
        // Update screen after user successfully signed in
        updateScreen()
        print("userDidSignInGoogle")
        listAudioFilesAndFolders()
    }

    func listAudioFilesAndFolders() {
        self.googleAPIs?.search(onCompleted: { files, error in
            guard error == nil, files != nil else {
                print("Err: \(String(describing: error))")
                return
            }
            
            self.dismiss(animated: true) {
                let vc = GoogleDriveFilesViewController()
                // filter the files before passing it.
                vc.audioFilesAndFolders = files?.filter { $0.mimeType == "audio/mpeg" || $0.mimeType == "application/vnd.google-apps.folder"}
                UIApplication.getTopMostViewController()?.present(vc, animated: true)
            }
        })
    }

Upvotes: 0

Linda Lawton - DaImTo
Linda Lawton - DaImTo

Reputation: 117196

if you do mimeType = 'application/vnd.google-apps.folder' then you are telling it that you only want folders or a specific mime type.

if you do 'root' in parents" it will return everything with a parent folder of root.

so if you do 'root' in parents" and mimeType = 'application/vnd.google-apps.folder' you will get all of the folders that have a parent folder of root.

Upvotes: 1

Related Questions