¿Cómo configurar las credenciales de Google Drive en la aplicación de Android?
La aplicación se registró en la "Consola de API de Google" como una "aplicación instalada" – parece que este es el ajuste correcto para una aplicación para Android, ¿no?
Así que tengo un Id de cliente y no secreto Id. 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.
- Android Oauth Exception con el transporte SMTP se conectan, con Android versión 2.3
- Cómo utilizar OAuth 2.0 con Retrofit Android
- Autorización de reutilización de GoogleAccountCredential: Google Drive
- Android Google+ no puede obtener el código de autorización
- Mejores prácticas de token de Android OAuth2 Bearer
Dentro de la aplicación busco la cuenta (works) y solicito un token (works). Ahora quiero conectarme a Google Drive con ese token y el Client-Id. El resultado es una "credencial 401 inválida". ¿Qué tiene de malo 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 una carga llena de lío. Hay tantas páginas en la web que muestra sólo partes y hay tantas páginas que utilizan métodos obsoletos, desaparecidos 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: Podría resolverlo yo mismo. Fue una combinación de diferentes cambios:
- Tenía que establecer android: minSdkVersion = "11" como requisito
- Tuvieron que usar las bibliotecas actuales: google-api-client-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, guava-11.0.1.jar, jackson-core -2.0.5.jar, jsr305-1.3.9.jar
Esta es la parte actual para obtener el objeto Drive:
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) { }
- ¿Cómo utilizar el tipo implícito de subvención en OAuth 2.0 para aplicaciones móviles?
- ¿Es seguro guardar los tokens de acceso / actualización de Oauth2 en las Preferencias compartidas de Android?
- Obtener la solicitud de permiso "tener acceso sin conexión" al llamar a GoogleAuthUtil.getToken
- ¿Cómo evitar la "Acción completa con" emergente con devoluciones de llamada de OAuth de Google?
- Seguridad de Primavera Angularjs + Android REST
- Acceso a Google API - GoogleAccountCredential.usingOAuth2 vs GoogleAuthUtil.getToken ()
- Validación y uso de auth_token de Android en el lado del servidor
- Autenticación de la API de Android Firebase Rest
Sí, la documentación es muy difícil de captar.
Solo 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 Consola de API de Google en la sección Acceso a API Simple de la página de Acceso a API (la API key
). Si esta sección no está disponible, primero debe activar el acceso a la API de unidad en la página Servicios .
Hay 2 problemas con el fragmento incluido.
-
Debe invalidar el antiguo authToken antes de buscar un nuevo
authToken
desde AccountManager.AccountManager.get(activity).invalidateAuthToken("com.google", authToken); accountManager.getAuthToken(...);
-
La llamada a
setJsonHttpRequestInitializer
debe utilizar la clave de API simple declarada en la consola de API para su proyecto.- Se puede obtener visitando la Consola de API .
- Haga clic en Acceso API en el menú de la izquierda.
- Busque el acceso simple a la API y copie la clave de la API .
-
Establezca la clave de API al crear el objeto Drive.
.setJsonHttpRequestInitializer (nuevo GoogleKeyInitializer (KEY))
Hay una pequeña muestra que demuestra la invalidación del token aquí: http://chiarg.com/?p=429
He intentado todo esto y finalmente encontré este código para trabajar con la api de Google Calendar. Solía obtener un 401 cada vez que utilicé GoogleCredentials y lo pasé 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(); }
He dado una respuesta extensa sobre el uso de Google Drive en Android por aquí:
Abrir y guardar archivos de Android en / desde el SDK de Google Drive
Utilizando los métodos que establezco en esa respuesta, puedo confirmar que puede hacer lo siguiente:
- Establecer y acceder a los metadatos
- Subir archivos
- Descargar archivos
- Mover archivos entre directorios de Google Drive
- Eliminar completamente los archivos de la unidad
- Solución para clases duplicadas en sabores Gradle y principales
- Los azulejos del mapa parpadean entre el terreno y los tipos normales