Inicio Android Google Drive en Android (1)

Google Drive en Android (1)

por sgoliver
drive-1-1

[mensaje-curso]

En este primer artículo de la serie sobre la API de Google Drive para Android veremos cómo configurar todos los elementos necesarios y a implementar algunas de las acciones básicas que podemos realizar sobre Google Drive, como la creación y eliminación de carpetas y ficheros.

Antes de comenzar a implementar nuestra aplicación, tendremos que registrar un nuevo proyecto en la Consola de Desarrolladores de Google de forma similar a como lo hicimos para el uso de otros servicios y añadirle las APIs necesarias. Como es algo con lo que ya deberíamos estar familiarizados (si no es así, revisar por ejemplo el primer articulo sobre Google Maps) pasaré muy rápidamente por todos los pasos necesarios.

En mi caso crearé un proyecto llamado «curso-android-drive» y en este caso añadiré la API «Drive API» para poder hacer uso de los servicios de Google Drive.

dev-console-2

Habilitamos la API pulsando en el botón superior «HABILITAR»:

dev-console-3

Y posteriormente pulsamos en «Ir a credenciales» para crear iniciar el proceso de creación de nuestro ID de Cliente (Client ID).

dev-console-4

En el primer paso indicamos la API que utilizaremos (Google Drive API), la plataforma desde la que vamos a utilizar el servicio (Android) y el tipo de datos a los que accederemos. Para este último dato seleccionaremos la opción «Datos de usuario» (la única opción válida disponible por el momento para la plataforma Android).

dev-console-5

En el siguiente paso daremos un nombre al ID de Cliente que estamos creando (en mi caso «Cliente de Android 1«), obtendremos como en otras ocasiones la huella digital SHA-1 del certificado de firma (recordad utilizar el certificado de prueba durante el desarrollo y cambiarlo por el certificado de producción cuando se distribuya la aplicación), e indicaremos el paquete java principal de nuestra aplicación Android.

dev-console-6

El tercer paso que nos muestra el asistente no lo conocíamos por ahora. Es éste tendremos que indicar una dirección de correo electrónico y un nombre de producto (nuestra aplicación), además de otros datos opcionales que obviaré para este ejemplo. Esta información se mostrará al usuario de la aplicación cuando se le solicite acceso a sus datos privados de Google Drive.

dev-console-7

Tras aceptar este paso, y si todo ha ido bien, ya tendremos generado nuestro nuevo ID de Cliente y habremos concluido los preparativos necesarios en la Consola de Desarrolladores. No es necesario descargar el fichero ya que en principio no necesitaremos este dato en nuestra aplicación Android (es suficiente con el registro realizado), de cualquier forma siempre podremos volver a la consola para consultarlo más adelante.

dev-console-8

Hecho esto, podemos dirigirnos ya a Android Studio para empezar a preparar nuestro proyecto. Crearemos un proyecto nuevo, utilizando como siempre la plantilla «Blank Activity» y resto de opciones por defecto.

Lo primero que haremos será añadir a nuestro fichero build.gradle la referencia a la librería específica de Google Drive perteneciente a los Google Play Services:

dependencies {
    //...
    compile 'com.google.android.gms:play-services-drive:9.6.1'
}

El siguiente paso, como ya hemos hecho para otros servicios de Google Play será crear en nuestra actividad principal (por ejemplo dentro del método onCreate()) un objeto de tipo GoogleApiClient, que utilizaremos como referencia en todas las operaciones sobre los servicios. Volveremos a usar una vez más la opción de Auto Manage (que gestionará automáticamente la conexión con los servicios dentro del ciclo de vida de la actividad), implementaremos en la clase principal la interfaz OnConnectionFailedListener y su método onConnectionFailed(), incluiremos la api de Google Drive añadiendo Drive.Api, y como ocurría por ejemplo cuando describimos el servicio de autenticación de Google, añadiremos también un scope determinado para los servicios. El scope utilizado determinará el nivel de visibilidad que tendrá nuestra aplicación sobre los elementos almacenados en la cuenta de Drive del usuario. En principio utilizaremos tan Drive.SCOPE_FILE (más adelante comentaremos otra alternativa), que nos dará acceso a todos los ficheros y carpetas que el usuario haya abierto o creado con nuestra aplicación. Es importante entender esto último, ya que es la fuente de muchas de las dudas/problemas que surgen con la utilización de esta API. Utilizando la API de Drive para Android proporcionada por los Servicios de Google Play no tendremos acceso directo a la totalidad de los elementos almacenados en la cuenta de Drive del usuario logueado, sino tan solo a aquellos que el usuario haya abierto o creado con nuestra aplicación. Si se necesita un mayor nivel de visibilidad será necesario utilizar la librería de Google APIs para clientes Java (Google APIs Client Library for Java). Esto último se sale del alcance de este artículo, pero podéis encontrar más información en el siguiente enlace.

La creación del cliente API quedaría por tanto de la siguiente forma:

private GoogleApiClient apiClient;

public class MainActivity extends AppCompatActivity
       implements GoogleApiClient.OnConnectionFailedListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        apiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this, this)
            .addApi(Drive.API)
            .addScope(Drive.SCOPE_FILE)
            .build();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Toast.makeText(this, "Error de conexion!", Toast.LENGTH_SHORT).show();
        Log.e(LOGTAG, "OnConnectionFailed: " + connectionResult);
    }
}

Hecho esto ya podríamos ejecutar por primera vez la aplicación para ver si todo está correctamente configurado. La primera vez que ejecutemos la aplicación, se mostrará al usuario un listado de todas las cuentas de Google del dispositivo, de forma que pueda seleccionar aquella con la que quiera acceder.

select-user

Una vez seleccionada, se mostrará también la pantalla de permisos, donde se informa al usuario de los recursos a los que va a acceder la aplicación.

drive-permissions-1

Si el usuario selecciona la opción PERMITIR nuestra aplicación se iniciará normalmente, aunque por el momento no hemos implementado ninguna funcionalidad.

Pero antes de empezar a describir las distintas funcionalidades de la API de Google Drive para Android, es importante conocer un poco el modelo de objetos que nos propone. Dada la natraleza de este servicio, las entidades principales que manejaremos serán por supuesto ficheros y carpetas. Estos elementos estarán representados por las clases DriveFile y DriveFolder respectivamente (ambas implementan la interfaz DriveResource). Tanto ficheros como carpetas poseen atributos comunes importantes, entre los que destacan el identificador único del elemento (representado por la clase DriveId) y un conjunto de metadatos (clase Metadata) que contendrán información relevante sobre la entidad, como por ejemplo su nombre o título, su tipo de contenido (o MIME type), su tamaño, sus fechas de creación y modificación, … En el caso de los ficheros, la entidad también contendrá otro elemento importante, clase DriveContents, que encapsulará el contenido del fichero.

Repasado el modelo de objetos principales que vamos a utilizar empecemos ya con la funcionalidad disponible.

Las operaciones realizadas sobre Google Drive seguirán casi siempre el mismo esquema:

  1. (Opcional) Definir los metadatos (MetadataChangeSet) a asociar al elemento sobre el que va a actuar la operación realizada.
  2. Llamar al método correspondiente a la operación (p.ej. abrir, crear, actualizar, eliminar, …)
  3. Definir y asignar a la operación un callback (de tipo ResultCallback) que será llamado automáticamente cuando ésta finalice.
  4. Actuar según el resultado de la operación dentro del método onResult() del callback definido.

Es posible que para alguna de las operaciones que vamos a describir realicemos algún paso adicional, pero lo comentaremos en su momento.

Vamos a empezar por una de las operaciones más sencillas, la creación de carpetas. Para crear una nueva carpeta en Google Drive seguiremos los pasos generales que acabamos de comentar. En primer lugar definiremos los metadatos de la nueva carpeta, que en este caso se limitarán a su título o nombre. Por tanto, lo que haremos será crear un objeto MetadataChangeSet mediante su Builder, y asignaremos el título llamando a su método setTitle().

MetadataChangeSet changeSet =
    new MetadataChangeSet.Builder()
        .setTitle(foldername)
        .build();

En segundo lugar obtendremos una referencia a la localización donde queremos crear la nueva carpeta. Esta localización podrá ser la carpeta raíz de Drive o alguna otra carpeta ya existente (más adelante veremos una tercera opción, la App Folder o carpeta de aplicación). Para obtener una referencia a la carpeta raíz podemos utilizar el método getRootFolder() de la API, que nos devolverá directamente su objeto DriveFolder correspondiente.

DriveFolder folder = Drive.DriveApi.getRootFolder(apiClient);

En breve veremos cómo crear la carpeta dentro de alguna otra carpeta distinta al directorio raíz.

Una vez tenemos los metadatos y la carpeta donde vamos a crear el nuevo elemento, ya tan sólo nos queda llamar al método de creación correspondiente, que en este caso será createFolder(). Llamaremos a este método sobre el DriveFolder base y le pasaremos como parámetros, además del omnipresente Cliente API, los metadatos definidos anteriormente. Como ya indicamos, sobre esta llamada asignaremos un callback de tipo ResultCallback cuyo método onResult() será llamado automáticamente cuando finalice la operación. Dentro de este método podremos saber si la finalización ha sido correcta a través del método isSuccess(). En nuestro caso de ejemplo, simplemente mostraremos un mensaje de log con el resultado de la operación, y en caso de haber sido correcta mostraremos adicionalmente el DriveId del nuevo elemento creado mediante los métodos getDriveFolder() y getDriveId().

Veamos el código completo de esta llamada, que ayudará a clarificar las cosas:

folder.createFolder(apiClient, changeSet).setResultCallback(
    new ResultCallback<DriveFolder.DriveFolderResult>() {
        @Override
        public void onResult(DriveFolder.DriveFolderResult result) {
            if (result.getStatus().isSuccess())
                Log.i(LOGTAG, "Carpeta creada con ID = " + result.getDriveFolder().getDriveId());
            else
                Log.e(LOGTAG, "Error al crear carpeta");
        }
    });

Si la nueva carpeta creada nos va a servir posteriormente como base para crear nuevos elementos en su interior es importante guardar su DriveId recibido en el método onResult(). Sobre este nuevo DriveId podríamos por ejemplo crear una otra nueva carpeta de la siguiente forma:

DriveFolder folder2 = nuevoDriveId.asDriveFolder();

folder2.createFolder(...)...

Si no guardamos el objeto DriveId como tal, también podremos obtenerlo a partir de su representación textual (la que obtuvimos dentro de onResult() imprimiendo en el log el resultado de getDriveId()). Este texto suele tener una forma similar a la siguiente: «DriveId:CAESABjKGSD6wKnM7lQoAQ==«. Si contamos con esta cadena de caracteres podemos reconstruir su objeto DriveId asociado llamando al método estático decodeFromString() de la clase DriveId de la siguiente forma:

DriveFolder folder3 =
    DriveId.decodeFromString("DriveId:CAESABjKGSD6wKnM7lQoAQ==").asDriveFolder();

folder3.createFolder(...).setResultCallback(...)

Por ser el primer ejemplo, vamos a recopilar cómo quedaría el método completo de creación de una nueva carpeta en Google Drive:

private void createFolder(final String foldername) {

    MetadataChangeSet changeSet =
        new MetadataChangeSet.Builder()
            .setTitle(foldername)
            .build();

    //Opción 1: Directorio raíz
    DriveFolder folder = Drive.DriveApi.getRootFolder(apiClient);

    //Opción 2: Otra carpeta distinta al directorio raiz
    //DriveFolder folder =
    //        DriveId.decodeFromString("DriveId:CAESABjKGSD6wKnM7lQoAQ==").asDriveFolder();

    folder.createFolder(apiClient, changeSet).setResultCallback(
        new ResultCallback<DriveFolder.DriveFolderResult>() {
            @Override
            public void onResult(DriveFolder.DriveFolderResult result) {
                if (result.getStatus().isSuccess())
                    Log.i(LOGTAG, "Carpeta creada con ID = " + result.getDriveFolder().getDriveId());
                else
                    Log.e(LOGTAG, "Error al crear carpeta");
            }
        });
}

Recordemos que no es recomendable realizar operaciones de I/O en el hilo principal de una aplicación Android, por lo que para llamar al método anterior deberíamos usar un hilo independiente. Para ello podríamos crear por ejemplo una tarea asíncrona o AsyncTask, pero por simplicidad, para nuestro ejemplo optaré por la ejecución directa del método en un nuevo hilo de ejecución creado manualmente. Así, por ejemplo, podríamos llamar al método desde el evento onClick() de un botón de la siguiente forma:

new Thread() {
    @Override
    public void run() {
        createFolder("Pruebas");
    }
}.start();

Si ejecutamos ahora la aplicación y lanzamos la operación de creación de la nueva carpeta, podremos comprobar en el log de Android el resultado esperado:

driveid-logcat

Y por supuesto podremos dirigirnos a nuestra cuenta de Google Drive a verificar que la carpeta se ha creado correctamente:

google-drive-demo-1

Vamos ahora con la creación de ficheros. La lógica para crear un fichero va a ser bastante similar a la ya vista para carpetas, aunque con la particularidad de que serán necesarias dos operaciones encadenadas para crear el fichero final, la primera de ellas construirá el contenido del fichero, objeto DriveContents, y la segunda creará el fichero como tal, objeto DriveFile, incluyendo dicho contenido.

Empezaremos creando el objeto DriveContents llamando al método newDriveContents() de la API de Google Drive. Como siempre, asignaremos un callback de tipo ResultCallback a dicha operación para ser notificados cuando ésta finalice. Si la operación ha finalizado con éxito (dato obtenido con isSuccess())  obtendremos una referencia al recién creado DriveContents mediante getDriveContents(), escribiremos el contenido del fichero sobre dicho DriveContents, definiremos los metadatos del nuevo fichero, obtendremos la carpeta base donde queremos crearlo (carpeta raíz u otra carpeta), y por último crearemos el fichero final a partir de toda la información anterior utilizando el método createFile(). Vayamos comentándolo paso por paso.

Una vez disponemos del nuevo DriveContents, para escribir sobre él podremos utilizar la API estandar de java para escritura sobre ficheros (como ejemplo será un fichero de texto, pero en realidad podría escribirse cualquier tipo de contenido). Para ello, a partir del objeto DriveContents obtendremos su stream de salida asociado en forma de OutputStream, crearemos a partir de éste un objeto Writer, y finalmente escribiremos el texto necesario utilizando el método write(). Finalmente cerraremos el stream con close(). Esta lógica no debería plantear ningún problema, veamos cómo quedaría el método auxiliar que emplearemos para escribir el contenido del fichero a partir del nuevo DriveContents:

private void writeSampleText(DriveContents driveContents) {
    OutputStream outputStream = driveContents.getOutputStream();
    Writer writer = new OutputStreamWriter(outputStream);

    try {
        writer.write("Esto es un texto de prueba!");
        writer.close();
    } catch (IOException e) {
        Log.e(LOGTAG, "Error al escribir en el fichero: " + e.getMessage());
    }
}

Para definir los metadatos utilizaremos el mismo método que para las carpetas, con la diferencia de que en esta ocasión asignaremos algún dato adicional además del nombre o título, por ejemplo el MIME Type mediante setMimeType(), que indicará el tipo de contenido de nuestro fichero. Como hemos indicado, para el ejemplo crearemos un fichero de texto por lo que nuestro MIME Type será «text/plain» (podéis consultar una lista bastante extensa con otros valores posibles en este enlace).

Como carpeta base utilizaremos una vez más la carpeta raíz de Drive, obtenida mediante getRootFolder(), aunque podríamos utilizar cualquier otra, a través de su DriveId, de la forma ya comentada en el apartado sobre creación de carpetas.

Por último, crearemos el fichero final con todos estos datos llamando a createFile() sobre la carpeta base, al que pasaremos como parámetros el cliente API, el conjunto de metadatos, y el objeto DriveContents que creamos y escribimos anteriormente. Como siempre, asignaremos un callback sobre esta llamada para ser notificados cuando finalice.

Veamos el código completo del método de creación de ficheros:

private void createFile(final String filename) {

    Drive.DriveApi.newDriveContents(apiClient)
        .setResultCallback(new ResultCallback<DriveApi.DriveContentsResult>() {
            @Override
            public void onResult(DriveApi.DriveContentsResult result) {
                if (result.getStatus().isSuccess()) {

                    writeSampleText(result.getDriveContents());

                    MetadataChangeSet changeSet = 
                        new MetadataChangeSet.Builder()
                            .setTitle(filename)
                            .setMimeType("text/plain")
                            .build();

                    //Opción 1: Directorio raíz
                    DriveFolder folder = Drive.DriveApi.getRootFolder(apiClient);

                    //Opción 2: Otra carpeta distinta al directorio raiz
                    //DriveFolder folder =
                    //    DriveId.decodeFromString("DriveId:CAESABjKGSD6wKnM7lQoAQ==").asDriveFolder();

                    folder.createFile(apiClient, changeSet, result.getDriveContents())
                        .setResultCallback(new ResultCallback<DriveFolder.DriveFileResult>() {
                            @Override
                            public void onResult(DriveFolder.DriveFileResult result) {
                                if (result.getStatus().isSuccess()) {
                                    Log.i(LOGTAG, "Fichero creado con ID = " + result.getDriveFile().getDriveId());
                                } else {
                                    Log.e(LOGTAG, "Error al crear el fichero");
                                }
                            }
                        });
                } else {
                    Log.e(LOGTAG, "Error al crear DriveContents");
                }
            }
        });
}

Este método, al igual que el anteriormente creado createFolder(), debemos ejecutarlo en un hilo de ejecución independiente, por ejemplo de la siguiente forma:

new Thread() {
    @Override
    public void run() {
        createFile("prueba1.txt");
    }
}.start();

Además de esta forma de crear ficheros totalmente programática, también tenemos la posibilidad de crearlos utilizando una actividad predefinida que permitirá al usuario seleccionar una ubicación y un nombre para el fichero.

Para hacer esto el proceso será muy similar al descrito anteriormente. Creamos un nuevo DriveContents mediante newDriveContents(), asignamos el callback correspondiente, y en su método onResult() definimos los metadatos (esta vez no asignamos ningún título), escribimos el texto de ejemplo sobre el DriveContents, y por último, como única novedad, en vez de crear directamente el fichero final con createFile(), creamos un IntentSender para lanzar la actividad de creación de ficheros en Drive. Lo crearemos llamando al método newCreateFileActivityBuilder() de la API de Google Drive. Sobre éste asignaremos nuestros metadatos con setInitialMetadata(), asignaremos el contenido inicial del fichero con setInitialDriveContents() y por último llamaremos al método build().

Construido el IntentSender ya solo nos queda lanzarlo para iniciar la actividad mediante startIntentSenderForResult(), al que pasaremos nuestro IntentSender y una constante arbitraria (en mi caso REQ_CREATE_FILE, definida con cualquier valor único) que nos ayudará a conocer el resultado de la actividad (es decir, lo que haya realizado el usuario sobre la actividad mostrada).

private void createFileWithActivity() {

    Drive.DriveApi.newDriveContents(apiClient)
        .setResultCallback(new ResultCallback<DriveApi.DriveContentsResult>() {
            @Override
            public void onResult(DriveApi.DriveContentsResult result) {
                MetadataChangeSet changeSet =
                    new MetadataChangeSet.Builder()
                        .setMimeType("text/plain")
                        .build();

                writeSampleText(result.getDriveContents());

                IntentSender intentSender = Drive.DriveApi
                    .newCreateFileActivityBuilder()
                    .setInitialMetadata(changeSet)
                    .setInitialDriveContents(result.getDriveContents())
                    .build(apiClient);

                try {
                    startIntentSenderForResult(
                        intentSender, REQ_CREATE_FILE, null, 0, 0, 0);
                } catch (IntentSender.SendIntentException e) {
                    Log.e(LOGTAG, "Error al iniciar actividad: Create File", e);
                }
            }
        });
}

Para conocer este resultado debemos sobrescribir el método onActivityResult() de nuestra actividad principal. En éste, filtraremos por la constante que hemos utilizado anteriormente (reqCode == REQ_CREATE_FILE) y revisaremos si el usuario ha finalizado correctamente el proceso (resultCode == RESULT_OK). En este caso ya podremos obtener el DriveId del nuevo fichero creado a partir de los datos «extra» contenidos en el intent que recibimos como parámetro. Concretamente lo obtendremos obteniendo el dato de tipo Parcelable con nombre OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case REQ_CREATE_FILE:
            if (resultCode == RESULT_OK) {
                DriveId driveId = data.getParcelableExtra(
                    OpenFileActivityBuilder.EXTRA_RESPONSE_DRIVE_ID);

                Log.i(LOGTAG, "Fichero creado con ID = " + driveId);
            }
            break;
        default:
            super.onActivityResult(requestCode, resultCode, data);
            break;
    }
}

Si ejecutamos ahora la aplicación y el método createFileWithActivity() veremos en nuestro dispositivo una pantalla como la siguiente:

create-file-activity-1

Como puede comprobarse, al usuario se le da la posibilidad de escribir un nombre para el fichero, y de seleccionar la carpeta donde guardarlo. Si dejamos seleccionada la opción «Mi unidad» el fichero se creará en la carpeta raíz de Drive. Si por el contrario pulsamos sobre la lista desplegable nos aparecerá una nueva pantalla donde podemos ver las carpetas y ficheros almacenados actualmente en la cuenta de Drive, de forma que se permite seleccionar una carpeta distinta a la carpeta raíz.

create-file-activity-2

Si pulsamos aquí el botón SELECCIONAR sobre la carpeta elegida y posteriormente el botón GUARDAR en la pantalla anterior, el fichero se creará con los datos indicados y aparecerá un mensaje de log con el DriveId del nuevo elemento.

La última operación que describiremos en este artículo será la eliminación de ficheros y carpetas de Google Drive. La eliminación de elementos se realiza mediante los métodos trash() o delete() de la interfaz DriveResource, por lo que aplica tanto a ficheros como carpetas. La diferencia entre ambos radica en que el primero envía el fichero o carpeta a la Papelera de Drive (de forma que podría recuperarse posteriormente si es necesario, utilizando el método untrash()) y el segundo elimina por completo el elemento sin pasar por la Papelera.

El esquema a seguir será el ya habitual, llamar al método de borrado correspondiente (trash o delete), asignar el callback, y actuar según el resultado dentro del método onResult(). Veamos por ejemplo cómo quedaría un método para eliminar ficheros a partir de su DriveId:

private void deleteFile(DriveId fileDriveId) {
    DriveFile file = fileDriveId.asDriveFile();

    //Opción 1: Enviar a la papelera
    file.trash(apiClient).setResultCallback(new ResultCallback<Status>() {
        @Override
        public void onResult(Status status) {
            if(status.isSuccess())
                Log.i(LOGTAG, "Fichero eliminado correctamente.");
            else
                Log.e(LOGTAG, "Error al eliminar el fichero");
        }
    });

    //Opción 2: Eliminar
    //file.delete(apiClient).setResultCallback(...)
}

Para no alargar más este artículo lo vamos a dejar aquí por el momento. En el siguiente artículo seguiremos repasando más funcionlidades ofrecidas por esta API, como la apertura, lectura y escritura de ficheros o la consulta y modificación de metadatos.

Puedes consultar y/o descargar el código completo de los ejemplos desarrollados en este artículo accediendo a la página del curso en GitHub.

[mensaje-curso]

También te puede interesar

6 comentarios

Google Drive en Android [Serie] | sgoliver.net 27/09/2016 - 15:01

[…] Google Drive en Android (1) [Act. Septiembre 2016] […]

Responder
Google Drive en Android (2) | sgoliver.net 29/09/2016 - 16:15

[…] el artículo anterior de esta serie sobre los servicios de Google Drive en Android ya vimos cómo configurar un nuevo […]

Responder
Carlos Salvador 24/01/2017 - 20:05

Hola Salvador, gracias por estos tutoriales. Necesitaría hacerte una consulta. En el caso de que en vez de crear un fichero de texto directamente en Drive, necesitara copiar un fichero ya existente en mi dispositivo como, por ejemplo, un fichero de base de datos de Sqlite, para guardarlo por seguridad, cómo lo podría hacer. Un saludo.

Responder
ruben dario prieto 11/05/2018 - 17:56

como sacar el DriveId de una carpeta especifica en drive…

Responder
ruben dario prieto 11/05/2018 - 17:59

DriveFolder folder3 =
DriveId.decodeFromString(«DriveId:CAESABjKGSD6wKnM7lQoAQ==»).asDriveFolder();
como sacar el DriveId

Responder
Mrthemendoza 11/03/2020 - 0:03

Hola,

Antes si podía acceder a mi usuario y crear carpetas y subir información, Después de subir a App a google play console y ser rechazada, De un rato para otro me pide que seleccione el usuario y me sale este error:

ConnectionResult{statusCode=API_UNAVAILABLE, resolution=null, message=null}

Ya intente cambiar la credencial de SHA1 y el nombre de la aplicación, deshabilitando y habilitando el API Drive y nada, alguien me puede ayudar.

Responder

Responder a Mrthemendoza Cancelar respuesta

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información. Aceptar Más Información

Política de Privacidad y Cookies