2012-09-13 15 views
9

La aplicación se registró en la "Consola de API de Google" como una "aplicación instalada": parece que esta es la configuración correcta para una aplicación de Android, ¿no?¿Cómo configuró las Credenciales de Google Drive dentro de la aplicación de Android?

Por lo tanto, tengo una Id. De cliente y ninguna ID secreta. Para dejarlo en claro: no es una aplicación web ni una aplicación de Google Drive: es una aplicación de Android que accede a los datos de otros usuarios en la nube de Google Drive.

Dentro de la aplicación, obtengo la cuenta (funciona) y solicito un token (funciona). Ahora quiero conectarme a Google Drive con ese token y el Id. Del cliente. El resultado es una "401, credencial no válida". ¿Qué pasa con este código?

public class ActivityMain extends Activity implements DialogInterface.OnClickListener { 

    // https://developers.google.com/drive/scopes 
    private static final String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/drive"; 

    // https://code.google.com/apis/console/ 
    private static final String CLIENT_ID = "999999999999999.apps.googleusercontent.com"; 

    private AccountManager accountManager; 
    private Account[] accounts; 
    private String authName; 
    private String authToken; 

    @Override 
    public void onClick(final DialogInterface dialogInterface, final int item) { 

     processAccountSelected(accounts[item]); 
    } 

    @Override 
    public void onCreate(final Bundle bundle) { 
     super.onCreate(bundle); 

     setContentView(R.layout.activitymain); 

     accountManager = AccountManager.get(this); 
     accounts = accountManager.getAccountsByType("com.google"); 

     if (accounts == null || accounts.length == 0) { 
      // TODO 
     } else if (accounts.length == 1) { 
      processAccountSelected(accounts[0]); 
     } else if (accounts.length > 1) { 
      showDialog(MyConstants.DIALOG_ACCOUNTCHOSER); 
     } 
    } 

    @Override 
    protected Dialog onCreateDialog(final int id) { 
     switch (id) { 
      case MyConstants.DIALOG_ACCOUNTCHOSER: 
       AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this); 

       String[] names = new String[accounts.length]; 

       for (int i = 0; i < accounts.length; i++) { 
        names[i] = accounts[i].name; 
       } 

       alertDialogBuilder.setItems(names, this); 
       alertDialogBuilder.setTitle("Select a Google account"); 
       return alertDialogBuilder.create(); 
     } 

     return null; 
    } 

    private void processAccountSelected(final Account account) { 
     if (account != null) { 
      authName = account.name.toString(); 
      if (!Tools.isEmpty(authName)) { 
       Toast.makeText(this, authName, Toast.LENGTH_LONG).show(); 

       accountManager.getAuthToken(account, AUTH_TOKEN_TYPE, null, this, 
         new AccountManagerCallback<Bundle>() { 

          public void run(final AccountManagerFuture<Bundle> future) { 
           try { 
            authToken = future.getResult().getString(
              AccountManager.KEY_AUTHTOKEN); 
            processTokenReceived(); 
           } catch (OperationCanceledException exception) { 
            // TODO 
           } catch (Exception exception) { 
            Log.d(this.getClass().getName(), exception.getMessage()); 
           } 
          } 
         }, null); 
      } 
     } 
    } 

    private void processListFiles(final Drive drive) { 
     List<File> result = new ArrayList<File>(); 
     Files.List request = null; 
     try { 
      request = drive.files().list(); 
     } catch (IOException exception) { 
     } 

     do { 
      try { 
       FileList files = request.execute(); 

       result.addAll(files.getItems()); 
       request.setPageToken(files.getNextPageToken()); 
      } catch (IOException exception) { 
       // --> 401 invalid credentials 
      } 
     } while (request.getPageToken() != null && request.getPageToken().length() > 0); 
    } 

    private void processTokenReceived() { 
     if (!Tools.isEmpty(authToken)) { 
      final HttpTransport transport = AndroidHttp.newCompatibleTransport(); 
      final JsonFactory jsonFactory = new GsonFactory(); 
      GoogleCredential credential = new GoogleCredential(); 
      credential.setAccessToken(authToken); 
      Drive drive = new Drive.Builder(transport, jsonFactory, credential) 
        .setApplicationName(getString(R.string.txt_appname)) 
        .setJsonHttpRequestInitializer(new GoogleKeyInitializer(CLIENT_ID)) 
        .build(); 

      if (drive != null) { 
       processListFiles(drive); 
      } 
     } 
    } 
} 

Tengo que decir que esto es un montón de desorden. Hay tantas páginas en la web que muestran solo partes y hay tantas páginas que usan métodos obsoletos, faltantes o diferentes para hacer lo mismo. En mi opinión, no hay dos páginas que muestren la misma forma de obtener datos de Google Drive desde una aplicación de Android.

Cualquier ayuda es muy apreciada.

EDIT: Pude resolverlo yo solo. Fue una combinación de diferentes cambios:

  • tuvo que establecer androide: minSdkVersion = "11" como requisito
  • tenido que utilizar esta bibliotecas actuales: google-api-cliente-1.11.0-beta.jar , google-api-client-android-1.11.0-beta.jar, google-api-services-drive-v2-rev9-1.8.0-beta.jar, google-http-client-1.11.0-beta.jar , google-http-client-android-1.11.0-beta.jar, google-http-client-gson-1.11.0-beta.jar, google-http-client-jackson2-1.11.0-beta.jar, google -oauth-client-1.11.0-beta.jar, GSON-2.1.jar, guayaba-11.0.1.jar, Jackson-core-2.0.5.jar, jsr305-1.3.9.jar

Este es el curren t parte para obtener el objeto de accionamiento:

GoogleCredential credential = new GoogleCredential(); 
    credential.setAccessToken(authToken); 

    HttpTransport transport = AndroidHttp.newCompatibleTransport(); 

    JsonFactory jsonFactory = new AndroidJsonFactory(); 

    drive = new Drive.Builder(transport, jsonFactory, credential) 
      .setApplicationName(getString(R.string.txt_appname)) 
      .setJsonHttpRequestInitializer(
        new GoogleKeyInitializer(APIKEY_SIMPLE)) 
      .build(); 
    if (drive != null) { 
    } 

Respuesta

3

Sí, la documentación es bastante difícil de entender.

Sólo cambia

new GoogleKeyInitializer(CLIENT_ID) 

a

new GoogleKeyInitializer(SIMPLE_API_ACCESS_KEY) 

y debería funcionar.

Puede encontrar su SIMPLE_API_ACCESS_KEY en la APIs Console en la sección API sencillo de acceso a de la API página Acceso (el API key) Google. Si esta sección no está disponible, primero debe activar el acceso de Drive API en la página Servicios.

+0

lo sentimos, no funcionó tampoco. Mismo error: 401, credencial no válida. La sección de la clave de API simple menciona "... cuando no es necesario acceder a los datos del usuario ...", pero esto es cierto para mi aplicación de Android. No lo entiendo ¿No hay nadie que haya creado correctamente una aplicación de Android que se conecte a datos de Google Drive en nombre de un usuario que dio permiso para hacerlo a través de AccountManager y Google Credentials? –

+0

Bueno, la única diferencia entre su código y el [Ejemplo de la API de tareas] (https://code.google.com/p/google-api-java-client/source/browse/tasks-android-sample/src/main/ java/com/google/api/services/samples/tasks/android/TasksSample.java? repo = samples) Veo entonces, es que están llamando 'credential.setAccessToken (authToken)' * después de * compilar 'Tasks' ejemplo. Entonces, ¿tal vez el intercambio de esas 2 líneas sea el truco? –

+0

Sin suerte. Parece que hay algo roto. Gracias de cualquier manera. –

0

Intenté todo esto y finalmente encontré que este código funcionaba con la aplicación Google Calendar. Solía ​​obtener un 401 cada vez que usaba GoogleCredentials y lo pasaba a la compilación.

HttpTransport transport = AndroidHttp.newCompatibleTransport();; 
    JsonFactory jsonFactory = new GsonFactory(); 
    HttpRequestInitializer httpRequestInitializer; 

    Log.i("Reached calendar builder", "Reached calendar builder"+accessToken); 

    //GoogleCredential credential = new GoogleCredential(); 

    httpRequestInitializer = new HttpRequestInitializer(){ 
     public void initialize(HttpRequest request) throws IOException 
     { 
       request.getHeaders().setAuthorization(GoogleHeaders.getGoogleLoginValue(accessToken)); 
     } 
    }; 

    Calendar service = new Calendar.Builder(transport, jsonFactory, httpRequestInitializer) 
    .setApplicationName("Meetrbus/1.0") 
    .setJsonHttpRequestInitializer(new GoogleKeyInitializer("API_KEY")) 
    .build(); 


} 
+0

Gracias por su respuesta. No funcionó. Probé tu código exacto con la clave de API simple -> 401.Mi aplicación es una "aplicación instalada" con un Id. De cliente que se tomó de la consola API. Dudo que una clave API simple funcione en combinación con una "aplicación instalada". –

1

Hay 2 problemas con el fragmento que incluyó.

  1. Usted debe invalidar la edad authToken antes de ir a buscar un nuevo authToken a partir del administrador de cuentas.

    AccountManager.get(activity).invalidateAuthToken("com.google", authToken); 
    accountManager.getAuthToken(...); 
    
  2. La llamada a setJsonHttpRequestInitializer debe utilizar la clave de API simple declarado en la consola de las API para su proyecto.

    • Se puede obtener visitando el APIs Console.
    • Haga clic en Acceso API en el menú de la izquierda.
    • Busque Acceso API simple, y copie la clave API.
    • Establezca la clave API al construir el objeto Drive.

      .setJsonHttpRequestInitializer (nueva GoogleKeyInitializer (CLAVE))

Hay una pequeña muestra de lo que demuestra la invalidación símbolo aquí: http://chiarg.com/?p=429

+0

¿Ha logrado crear una aplicación de Android que pueda descargar archivos de Google Drive? Si es así, ¿te importaría compartir el código que lo hace? Según mi leal saber y entender, tengo la aplicación Drive más completa, no de Google, que funciona en Android, y no puedo hacer que funcione la descarga de archivos (siempre obtengo un error 401 ... de alguna manera tengo permiso para eliminar archivos por completo). , o cambiar completamente sus contenidos, pero no descargar los contenidos actuales?) Mi código está aquí: http://stackoverflow.com/questions/12164024/android-open-and-save-files-to-from-google-drive- sdk/12321331 # 12321331 – ArtOfWarfare

0

me dio una amplia respuesta en el uso de Google Drive en Android aquí:

Android Open and Save files to/from Google Drive SDK

Utilizando los métodos yo estaba a cabo en esa respuesta, puedo confirmar que usted es capaz de hacer lo siguiente:

  • Conjunto y Acceso Los meta-datos
  • Cargar archivos
  • Descargar archivos
  • mover archivos entre directorios de Google drive
  • Eliminar archivos fuera de la unidad del todo
Cuestiones relacionadas