Error al conectarse a la API de Google Drive (Swift 5)

Sep 15 2020

Quiero conectarme a la API de Google Drive en mi aplicación para mostrar una lista de archivos de usuario y poder descargarlos en el dispositivo. Estoy siguiendo este ejemplo Integrar Google Drive en la aplicación iOS

Conecté el SDK de Google y autoricé correctamente al usuario. Sin embargo, no puedo obtener la lista de sus archivos de ninguna manera. Sigo recibiendo el siguiente error:

"Se superó el límite diario de uso no autenticado. El uso continuo requiere registrarse".

Revisé mi aplicación y configuración en Google Console muchas veces, hice todo paso a paso, pero aún así no pude resolver este problema. Alguien ha experimentado el mismo problema?

Mi código y capturas de pantalla:

//class AppDelegate...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        GIDSignIn.sharedInstance().clientID = "Me client ID"
        return true
}

//class myVC: GIDSignInDelegate...
override func viewDidLoad() {
        super.viewDidLoad() 
        GIDSignIn.sharedInstance().presentingViewController = self
        GIDSignIn.sharedInstance().delegate = self
        GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDrive]
        GIDSignIn.sharedInstance().restorePreviousSignIn()
}

func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!,
              withError error: Error!) {
        if let error = error {
            print("Google autorization error: \(error.localizedDescription)")
            return
        }
        guard let token = user.authentication.accessToken else { return }
    SourceAuthorizationStateManager.shared.addAuthorizedSource(.googleDrive)
    
    let fullName = user.profile.name
    print("Google authorization successful. User name: \(fullName ?? "Error: no user name")\nUser token: \(token)")
}

//class GoogleDriveFileListSource...
private var fileListTicket: GTLRServiceTicket?
var files: [FileModelProtocol] {
        guard let files = fileList?.files else { return [] }
        return files.map { GoogleDriveFileModel($0) }
}

lazy var driveService: GTLRDriveService = {
    let service = GTLRDriveService()
    service.shouldFetchNextPages = true
    service.isRetryEnabled = true
    return service
}()

func fetchFileList(path: String?, _ completion: @escaping () -> Void) {
        let query = GTLRDriveQuery_FilesList.query()
        query.fields = "kind,nextPageToken,files(mimeType,id,kind,name,webViewLink,thumbnailLink,trashed)"
        
        fileListTicket = driveService.executeQuery(query,
                                                   completionHandler: { [weak self] (_, resultObject, error) in
                                                    if let error = error {
                                                        debugPrint("driveService.executeQuery error: \(error.localizedDescription)")
                                                        return
                                                    }
                                                    
                                                    guard let self = self,
                                                        let fileList = resultObject as? GTLRDrive_FileList else { return }
                                                    
                                                    self.fileList = fileList
                                                    self.fileListTicket = nil
                                                    
                                                    completion()
     })
}

Respuestas

1 DaImTo Sep 15 2020 at 14:54

"Se superó el límite diario de uso no autenticado.

Significa que no estás autorizado. Las llamadas a las API de Google que exponen datos privados del usuario deben incluir un token de portador de encabezado de autorización que contenga un token de acceso.

Parece que estás enviando algo llamado token de usuario que no creo que sea lo mismo que configurar el encabezado de autorización.

intento de depuración

Tenga en cuenta que nunca he tenido un dispositivo Apple. No soy un desarrollador de Ios o rápido. He trabajado con las API y la biblioteca de Google durante años.

Por lo que puedo ver, estás llamando

fileListTicket = driveService.executeQuery(query,

Mientras el tutorial está siguiendo las llamadas

self.service.executeQuery(query)

No cambiaste la delicada configuración

GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().uiDelegate = self

¿Porque lo cambiaste?

1 VyacheslavBakinkskiy Sep 16 2020 at 17:31

Resuelto. Gracias a todos los que ayudaron. Todo lo que tenía que hacer era transferir el estado de autenticación del usuario a driveService e importar GTMSessionFetcher a mis archivos.

var googleUser: GIDGoogleUser?
class myVC: GIDSignInDelegate {
...
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!,
              withError error: Error!) {
        if let error = error {
            print("Google autorization error: \(error.localizedDescription)")
            return
        }
        guard let token = user.authentication.accessToken else { return }
    SourceAuthorizationStateManager.shared.addAuthorizedSource(.googleDrive)
    googleUser = user   //Here I have saved the current user

    let fullName = user.profile.name
    print("Google authorization successful. User name: \(fullName ?? "Error: no user name")\nUser token: \(token)")
}
}

class GoogleDriveFileListSource {
...
lazy var driveService: GTLRDriveService = {
    let service = GTLRDriveService()
    if let user = googleUser {
    service.authorizer = user.authentication.fetcherAuthorizer() //Here I passed the status
    }
    service.shouldFetchNextPages = true
    service.isRetryEnabled = true
    return service
}()
}

Ahora que el código no se ve muy bien, pensaré en cómo mejorarlo. Pero esto ya funciona, obtengo la lista de archivos del usuario.